mirror of
https://github.com/systemd/systemd
synced 2026-04-21 22:44:51 +02:00
Compare commits
25 Commits
bd4f672e4c
...
a549442fff
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a549442fff | ||
|
|
6ccc08954e | ||
|
|
6e4d122ad1 | ||
|
|
b547838000 | ||
|
|
05d8ad0f85 | ||
|
|
cab4ed0f4a | ||
|
|
aff3a9e1fa | ||
|
|
56b96db700 | ||
|
|
5717062e93 | ||
|
|
b491d74064 | ||
|
|
09d0758b22 | ||
|
|
92148fb777 | ||
|
|
be99883e13 | ||
|
|
1da5325d19 | ||
|
|
19962747ca | ||
|
|
3f9973bf36 | ||
|
|
1cb5d7857b | ||
|
|
282696ce52 | ||
|
|
8306912b0e | ||
|
|
2e37084fc9 | ||
|
|
62d4b3b36e | ||
|
|
07b7337aff | ||
|
|
38488babe7 | ||
|
|
a6d6a51d83 | ||
|
|
d9fe39b24a |
@ -46,7 +46,7 @@ ColumnLimit: 109
|
||||
CompactNamespaces: true
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 8
|
||||
ContinuationIndentWidth: 8
|
||||
ContinuationIndentWidth: 16
|
||||
Cpp11BracedListStyle: false
|
||||
ForEachMacros:
|
||||
- BITMAP_FOREACH
|
||||
|
||||
4
.github/workflows/build_test.sh
vendored
4
.github/workflows/build_test.sh
vendored
@ -78,12 +78,12 @@ if [[ "$COMPILER" == clang ]]; then
|
||||
# ATTOW llvm-11 got into focal-updates, which conflicts with llvm-11
|
||||
# provided by the apt.llvm.org repositories. Let's use the system
|
||||
# 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/
|
||||
# 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
|
||||
printf "deb [signed-by=/usr/share/keyrings/apt-llvm-org.gpg] http://apt.llvm.org/%s/ llvm-toolchain-%s-%s main\n" \
|
||||
"$RELEASE" "$RELEASE" "$COMPILER_VERSION" >/etc/apt/sources.list.d/llvm-toolchain.list
|
||||
"$RELEASE" "$RELEASE" "$COMPILER_VERSION" >/etc/apt/sources.list.d/llvm-toolchain.list
|
||||
PACKAGES+=("clang-$COMPILER_VERSION" "lldb-$COMPILER_VERSION" "lld-$COMPILER_VERSION" "clangd-$COMPILER_VERSION")
|
||||
fi
|
||||
elif [[ "$COMPILER" == gcc ]]; then
|
||||
|
||||
@ -428,6 +428,28 @@
|
||||
</listitem>
|
||||
</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>
|
||||
<term><varname>systemd.cpu_affinity=</varname></term>
|
||||
|
||||
|
||||
@ -402,6 +402,12 @@ node /org/freedesktop/systemd1 {
|
||||
readwrite t RuntimeWatchdogUSec = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
|
||||
@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 = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
|
||||
@org.freedesktop.systemd1.Privileged("true")
|
||||
@ -650,6 +656,10 @@ node /org/freedesktop/systemd1 {
|
||||
|
||||
<!--property RuntimeWatchdogUSec is not documented!-->
|
||||
|
||||
<!--property RuntimeWatchdogPreUSec is not documented!-->
|
||||
|
||||
<!--property RuntimeWatchdogPreGovernor is not documented!-->
|
||||
|
||||
<!--property RebootWatchdogUSec 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="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="KExecWatchdogUSec"/>
|
||||
|
||||
@ -177,6 +177,50 @@
|
||||
<para>These settings have no effect if a hardware watchdog is not available.</para></listitem>
|
||||
</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>
|
||||
<term><varname>WatchdogDevice=</varname></term>
|
||||
|
||||
|
||||
@ -182,6 +182,9 @@ static BOOLEAN line_edit(
|
||||
cursor_color = TEXT_ATTR_SWAP(cursor_color);
|
||||
|
||||
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);
|
||||
} while (EFI_ERROR(err));
|
||||
|
||||
@ -436,8 +439,16 @@ static void ps_bool(const CHAR16 *fmt, BOOLEAN value) {
|
||||
Print(fmt, yes_no(value));
|
||||
}
|
||||
|
||||
static void print_status(Config *config, CHAR16 *loaded_image_path) {
|
||||
static BOOLEAN ps_continue(void) {
|
||||
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;
|
||||
UINT32 screen_width = 0, screen_height = 0;
|
||||
SecureBootMode secure;
|
||||
@ -468,8 +479,8 @@ static void print_status(Config *config, CHAR16 *loaded_image_path) {
|
||||
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"\n--- Press any key to continue. ---\n\n");
|
||||
console_key_read(&key, UINT64_MAX);
|
||||
if (!ps_continue())
|
||||
return;
|
||||
|
||||
switch (config->timeout_sec_config) {
|
||||
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)
|
||||
Print(L"console-mode (EFI var): %ld\n", config->console_mode_efivar);
|
||||
|
||||
Print(L"\n--- Press any key to continue. ---\n\n");
|
||||
console_key_read(&key, UINT64_MAX);
|
||||
if (!ps_continue())
|
||||
return;
|
||||
|
||||
for (UINTN i = 0; i < config->entry_count; 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"\n--- Press any key to continue, ESC or q to quit. ---\n\n");
|
||||
console_key_read(&key, UINT64_MAX);
|
||||
if (key == KEYPRESS(0, SCAN_ESC, 0) || key == KEYPRESS(0, 0, 'q') || key == KEYPRESS(0, 0, 'Q'))
|
||||
break;
|
||||
if (!ps_continue())
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -734,7 +743,12 @@ static BOOLEAN menu_run(
|
||||
beep(idx_highlight + 1);
|
||||
|
||||
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) {
|
||||
assert(timeout_remain > 0);
|
||||
timeout_remain--;
|
||||
if (timeout_remain == 0) {
|
||||
exit = TRUE;
|
||||
@ -743,8 +757,13 @@ static BOOLEAN menu_run(
|
||||
|
||||
/* update status */
|
||||
continue;
|
||||
} else
|
||||
timeout_remain = 0;
|
||||
}
|
||||
if (EFI_ERROR(err)) {
|
||||
exit = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
timeout_remain = 0;
|
||||
|
||||
/* clear status after keystroke */
|
||||
if (status) {
|
||||
|
||||
@ -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. */
|
||||
if (conInEx) {
|
||||
EFI_KEY_DATA keydata;
|
||||
UINT64 keypress;
|
||||
UINT32 shift = 0;
|
||||
|
||||
err = conInEx->ReadKeyStrokeEx(conInEx, &keydata);
|
||||
if (EFI_ERROR(err))
|
||||
return err;
|
||||
|
||||
/* do not distinguish between left and right keys */
|
||||
if (keydata.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) {
|
||||
if (keydata.KeyState.KeyShiftState & (EFI_RIGHT_CONTROL_PRESSED|EFI_LEFT_CONTROL_PRESSED))
|
||||
if (FLAGS_SET(keydata.KeyState.KeyShiftState, EFI_SHIFT_STATE_VALID)) {
|
||||
/* Do not distinguish between left and right keys (set both flags). */
|
||||
if (keydata.KeyState.KeyShiftState & EFI_SHIFT_PRESSED)
|
||||
shift |= EFI_SHIFT_PRESSED;
|
||||
if (keydata.KeyState.KeyShiftState & 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;
|
||||
if (keydata.KeyState.KeyShiftState & EFI_LOGO_PRESSED)
|
||||
shift |= EFI_LOGO_PRESSED;
|
||||
}
|
||||
|
||||
/* 32 bit modifier keys + 16 bit scan code + 16 bit unicode */
|
||||
keypress = KEYPRESS(shift, keydata.Key.ScanCode, keydata.Key.UnicodeChar);
|
||||
if (keypress > 0) {
|
||||
*key = keypress;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
return EFI_NOT_READY;
|
||||
*key = KEYPRESS(shift, keydata.Key.ScanCode, keydata.Key.UnicodeChar);
|
||||
return EFI_SUCCESS;
|
||||
} else if (!EFI_ERROR(BS->CheckEvent(ST->ConIn->WaitForKey))) {
|
||||
EFI_INPUT_KEY k;
|
||||
|
||||
|
||||
@ -3,10 +3,15 @@
|
||||
|
||||
#include "missing_efi.h"
|
||||
|
||||
#define EFI_CONTROL_PRESSED (EFI_RIGHT_CONTROL_PRESSED|EFI_LEFT_CONTROL_PRESSED)
|
||||
#define EFI_ALT_PRESSED (EFI_RIGHT_ALT_PRESSED|EFI_LEFT_ALT_PRESSED)
|
||||
enum {
|
||||
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 KEYCHAR(k) ((k) & 0xffff)
|
||||
#define KEYCHAR(k) ((CHAR16)(k))
|
||||
#define CHAR_CTRL(c) ((c) - 'a' + 1)
|
||||
|
||||
enum {
|
||||
|
||||
@ -13,10 +13,14 @@
|
||||
#define SimpleTextInputExProtocol ((EFI_GUID)EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID)
|
||||
|
||||
#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_LEFT_CONTROL_PRESSED 0x00000008
|
||||
#define EFI_RIGHT_ALT_PRESSED 0x00000010
|
||||
#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;
|
||||
|
||||
|
||||
@ -265,6 +265,42 @@ static int property_get_runtime_watchdog(
|
||||
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(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
@ -330,6 +366,42 @@ static int property_set_runtime_watchdog(
|
||||
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(
|
||||
sd_bus *bus,
|
||||
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("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("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),
|
||||
/* 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),
|
||||
|
||||
@ -138,7 +138,9 @@ static unsigned arg_default_start_limit_burst;
|
||||
static usec_t arg_runtime_watchdog;
|
||||
static usec_t arg_reboot_watchdog;
|
||||
static usec_t arg_kexec_watchdog;
|
||||
static usec_t arg_pretimeout_watchdog;
|
||||
static char *arg_early_core_pattern;
|
||||
static char *arg_watchdog_pretimeout_governor;
|
||||
static char *arg_watchdog_device;
|
||||
static char **arg_default_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;
|
||||
|
||||
} 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")) {
|
||||
|
||||
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", "JoinControllers", config_parse_warn_compat, DISABLED_CONFIGURATION, NULL },
|
||||
{ "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", "ShutdownWatchdogSec", config_parse_watchdog_sec, 0, &arg_reboot_watchdog }, /* obsolete alias */
|
||||
{ "Manager", "KExecWatchdogSec", config_parse_watchdog_sec, 0, &arg_kexec_watchdog },
|
||||
{ "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", "NoNewPrivileges", config_parse_bool, 0, &arg_no_new_privs },
|
||||
#if HAVE_SECCOMP
|
||||
@ -837,6 +872,7 @@ static void set_manager_defaults(Manager *m) {
|
||||
}
|
||||
|
||||
static void set_manager_settings(Manager *m) {
|
||||
int r;
|
||||
|
||||
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_REBOOT, arg_reboot_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");
|
||||
m->status_unit_format = arg_status_unit_format;
|
||||
@ -1595,7 +1635,10 @@ static int become_shutdown(
|
||||
watchdog_timer = arg_kexec_watchdog;
|
||||
|
||||
/* 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);
|
||||
watchdog_close(r < 0);
|
||||
|
||||
@ -2448,8 +2491,10 @@ static void reset_arguments(void) {
|
||||
arg_runtime_watchdog = 0;
|
||||
arg_reboot_watchdog = 10 * USEC_PER_MINUTE;
|
||||
arg_kexec_watchdog = 0;
|
||||
arg_pretimeout_watchdog = 0;
|
||||
arg_early_core_pattern = NULL;
|
||||
arg_watchdog_device = NULL;
|
||||
arg_watchdog_pretimeout_governor = mfree(arg_watchdog_pretimeout_governor);
|
||||
|
||||
arg_default_environment = strv_free(arg_default_environment);
|
||||
arg_manager_environment = strv_free(arg_manager_environment);
|
||||
|
||||
@ -118,6 +118,8 @@ int manager_serialize(
|
||||
(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, "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++) {
|
||||
_cleanup_free_ char *joined = NULL;
|
||||
@ -455,6 +457,19 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
|
||||
else
|
||||
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=")) {
|
||||
r = deserialize_environment(l + 4, &m->client_environment);
|
||||
if (r < 0)
|
||||
|
||||
@ -813,6 +813,7 @@ int manager_new(UnitFileScope scope, ManagerTestRunFlags test_run_flags, Manager
|
||||
.watchdog_overridden[WATCHDOG_RUNTIME] = USEC_INFINITY,
|
||||
.watchdog_overridden[WATCHDOG_REBOOT] = USEC_INFINITY,
|
||||
.watchdog_overridden[WATCHDOG_KEXEC] = USEC_INFINITY,
|
||||
.watchdog_overridden[WATCHDOG_PRETIMEOUT] = USEC_INFINITY,
|
||||
|
||||
.show_status_overridden = _SHOW_STATUS_INVALID,
|
||||
|
||||
@ -1541,6 +1542,9 @@ Manager* manager_free(Manager *m) {
|
||||
m->prefix[dt] = mfree(m->prefix[dt]);
|
||||
free(m->received_credentials);
|
||||
|
||||
free(m->watchdog_pretimeout_governor);
|
||||
free(m->watchdog_pretimeout_governor_overridden);
|
||||
|
||||
#if BPF_FRAMEWORK
|
||||
lsm_bpf_destroy(m->restrict_fs);
|
||||
#endif
|
||||
@ -3232,9 +3236,12 @@ void manager_set_watchdog(Manager *m, WatchdogType t, usec_t timeout) {
|
||||
if (m->watchdog[t] == timeout)
|
||||
return;
|
||||
|
||||
if (t == WATCHDOG_RUNTIME)
|
||||
if (t == WATCHDOG_RUNTIME) {
|
||||
if (!timestamp_is_set(m->watchdog_overridden[WATCHDOG_RUNTIME]))
|
||||
(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;
|
||||
}
|
||||
@ -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];
|
||||
|
||||
(void) watchdog_setup(usec);
|
||||
}
|
||||
} else if (t == WATCHDOG_PRETIMEOUT)
|
||||
(void) watchdog_setup_pretimeout(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) {
|
||||
_unused_ _cleanup_(manager_reloading_stopp) Manager *reloading = NULL;
|
||||
_cleanup_fdset_free_ FDSet *fds = NULL;
|
||||
|
||||
@ -118,6 +118,7 @@ typedef enum WatchdogType {
|
||||
WATCHDOG_RUNTIME,
|
||||
WATCHDOG_REBOOT,
|
||||
WATCHDOG_KEXEC,
|
||||
WATCHDOG_PRETIMEOUT,
|
||||
_WATCHDOG_TYPE_MAX,
|
||||
} WatchdogType;
|
||||
|
||||
@ -247,6 +248,8 @@ struct Manager {
|
||||
|
||||
usec_t watchdog[_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];
|
||||
|
||||
@ -574,6 +577,8 @@ ManagerTimestamp manager_timestamp_initrd_mangle(ManagerTimestamp s);
|
||||
usec_t manager_get_watchdog(Manager *m, WatchdogType t);
|
||||
void manager_set_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_;
|
||||
OOMPolicy oom_policy_from_string(const char *s) _pure_;
|
||||
|
||||
@ -30,6 +30,8 @@
|
||||
#NUMAPolicy=default
|
||||
#NUMAMask=
|
||||
#RuntimeWatchdogSec=off
|
||||
#RuntimeWatchdogPreSec=off
|
||||
#RuntimeWatchdogPreGovernor=
|
||||
#RebootWatchdogSec=10min
|
||||
#KExecWatchdogSec=off
|
||||
#WatchdogDevice=
|
||||
|
||||
@ -31,13 +31,6 @@ static bool verbose = true;
|
||||
static int test_fd[2];
|
||||
static test_callback_recv_t callback_recv;
|
||||
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) {
|
||||
int r;
|
||||
@ -514,19 +507,15 @@ static void test_addr_acq(sd_event *e) {
|
||||
|
||||
callback_recv = test_addr_acq_recv_discover;
|
||||
|
||||
assert_se(sd_event_add_time_relative(
|
||||
e, &test_hangcheck,
|
||||
clock_boottime_or_monotonic(),
|
||||
2 * USEC_PER_SEC, 0,
|
||||
test_dhcp_hangcheck, NULL) >= 0);
|
||||
assert_se(sd_event_add_time_relative(e, NULL, clock_boottime_or_monotonic(),
|
||||
2 * USEC_PER_SEC, 0,
|
||||
NULL, INT_TO_PTR(-ETIMEDOUT)) >= 0);
|
||||
|
||||
res = sd_dhcp_client_start(client);
|
||||
assert_se(IN_SET(res, 0, -EINPROGRESS));
|
||||
|
||||
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_stop(client) >= 0);
|
||||
sd_dhcp_client_unref(client);
|
||||
|
||||
@ -78,8 +78,6 @@ static int test_ifindex = 42;
|
||||
static unsigned test_client_sent_message_count = 0;
|
||||
static sd_dhcp6_client *client_ref = NULL;
|
||||
|
||||
STATIC_DESTRUCTOR_REGISTER(client_ref, sd_dhcp6_client_unrefp);
|
||||
|
||||
static void test_client_basic(void) {
|
||||
_cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
|
||||
int v;
|
||||
@ -981,7 +979,7 @@ static void test_dhcp6_client(void) {
|
||||
assert_se(sd_event_new(&e) >= 0);
|
||||
assert_se(sd_event_add_time_relative(e, NULL, clock_boottime_or_monotonic(),
|
||||
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_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(!sd_dhcp6_client_unref(client_ref));
|
||||
test_fd[1] = safe_close(test_fd[1]);
|
||||
}
|
||||
|
||||
|
||||
@ -51,7 +51,6 @@ static uint8_t advertisement[] = {
|
||||
0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
static sd_event_source *test_hangcheck;
|
||||
static bool test_stopped;
|
||||
static int test_fd[2];
|
||||
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",
|
||||
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) {
|
||||
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],
|
||||
EPOLLIN, radv_recv, ra) >= 0);
|
||||
|
||||
assert_se(sd_event_add_time_relative(
|
||||
e, &test_hangcheck, clock_boottime_or_monotonic(),
|
||||
2 *USEC_PER_SEC, 0,
|
||||
test_rs_hangcheck, NULL) >= 0);
|
||||
assert_se(sd_event_add_time_relative(e, NULL, clock_boottime_or_monotonic(),
|
||||
2 * USEC_PER_SEC, 0,
|
||||
NULL, INT_TO_PTR(-ETIMEDOUT)) >= 0);
|
||||
|
||||
assert_se(sd_radv_start(ra) >= 0);
|
||||
|
||||
sd_event_loop(e);
|
||||
|
||||
test_hangcheck = sd_event_source_unref(test_hangcheck);
|
||||
assert_se(sd_event_loop(e) >= 0);
|
||||
|
||||
ra = sd_radv_unref(ra);
|
||||
assert_se(!ra);
|
||||
|
||||
@ -22,7 +22,6 @@ static struct ether_addr mac_addr = {
|
||||
};
|
||||
|
||||
static bool verbose = false;
|
||||
static sd_event_source *test_hangcheck;
|
||||
static int test_fd[2];
|
||||
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) {
|
||||
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_callback(nd, test_callback, e) >= 0);
|
||||
|
||||
assert_se(sd_event_add_time_relative(
|
||||
e, &test_hangcheck, clock_boottime_or_monotonic(),
|
||||
30 * USEC_PER_SEC, 0,
|
||||
test_rs_hangcheck, NULL) >= 0);
|
||||
assert_se(sd_event_add_time_relative(e, NULL, clock_boottime_or_monotonic(),
|
||||
30 * USEC_PER_SEC, 0,
|
||||
NULL, INT_TO_PTR(-ETIMEDOUT)) >= 0);
|
||||
|
||||
assert_se(sd_ndisc_stop(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);
|
||||
|
||||
sd_event_loop(e);
|
||||
|
||||
test_hangcheck = sd_event_source_unref(test_hangcheck);
|
||||
assert_se(sd_event_loop(e) >= 0);
|
||||
|
||||
nd = sd_ndisc_unref(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_mac(nd, &mac_addr) >= 0);
|
||||
|
||||
assert_se(sd_event_add_time_relative(
|
||||
e, &test_hangcheck, clock_boottime_or_monotonic(),
|
||||
30 * USEC_PER_SEC, 0,
|
||||
test_rs_hangcheck, NULL) >= 0);
|
||||
assert_se(sd_event_add_time_relative(e, NULL, clock_boottime_or_monotonic(),
|
||||
30 * USEC_PER_SEC, 0,
|
||||
NULL, INT_TO_PTR(-ETIMEDOUT)) >= 0);
|
||||
|
||||
assert_se(sd_ndisc_start(nd) >= 0);
|
||||
|
||||
sd_event_loop(e);
|
||||
|
||||
test_hangcheck = sd_event_source_unref(test_hangcheck);
|
||||
assert_se(sd_event_loop(e) >= 0);
|
||||
|
||||
nd = sd_ndisc_unref(nd);
|
||||
|
||||
|
||||
@ -196,6 +196,7 @@ static void test_catalog_file_lang(void) {
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
_cleanup_(unlink_tempfilep) char database[] = "/tmp/test-catalog.XXXXXX";
|
||||
_cleanup_close_ int fd = -1;
|
||||
_cleanup_free_ char *text = NULL;
|
||||
int r;
|
||||
|
||||
@ -218,7 +219,7 @@ int main(int argc, char *argv[]) {
|
||||
test_catalog_import_merge();
|
||||
test_catalog_import_merge_no_body();
|
||||
|
||||
assert_se(mkostemp_safe(database) >= 0);
|
||||
assert_se((fd = mkostemp_safe(database)) >= 0);
|
||||
|
||||
test_catalog_update(database);
|
||||
|
||||
|
||||
@ -252,8 +252,8 @@ static int generate_addresses(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dhcp_pd_generate_addresses(Link *link, const struct in6_addr *prefix, uint8_t prefixlen, Set **ret) {
|
||||
return generate_addresses(link, link->network->dhcp_pd_tokens, &DHCP_PD_APP_ID, prefix, prefixlen, 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, 64, ret);
|
||||
}
|
||||
|
||||
int ndisc_generate_addresses(Link *link, const struct in6_addr *prefix, uint8_t prefixlen, Set **ret) {
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
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 radv_generate_addresses(Link *link, Set *tokens, const struct in6_addr *prefix, uint8_t prefixlen, Set **ret);
|
||||
|
||||
|
||||
@ -307,7 +307,7 @@ static int dhcp_pd_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *
|
||||
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;
|
||||
Route *existing;
|
||||
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->family = AF_INET6;
|
||||
route->dst.in6 = *prefix;
|
||||
route->dst_prefixlen = prefixlen;
|
||||
route->dst_prefixlen = 64;
|
||||
route->protocol = RTPROT_DHCP;
|
||||
route->priority = link->network->dhcp_pd_route_metric;
|
||||
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(
|
||||
Link *link,
|
||||
const struct in6_addr *prefix,
|
||||
uint8_t prefixlen,
|
||||
usec_t lifetime_preferred_usec,
|
||||
usec_t lifetime_valid_usec) {
|
||||
|
||||
@ -401,7 +400,7 @@ static int dhcp_pd_request_address(
|
||||
if (!link->network->dhcp_pd_assign)
|
||||
return 0;
|
||||
|
||||
r = dhcp_pd_generate_addresses(link, prefix, prefixlen, &addresses);
|
||||
r = dhcp_pd_generate_addresses(link, prefix, &addresses);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to generate addresses for acquired DHCP delegated prefix: %m");
|
||||
|
||||
@ -416,11 +415,10 @@ static int dhcp_pd_request_address(
|
||||
address->source = NETWORK_CONFIG_SOURCE_DHCP_PD;
|
||||
address->family = AF_INET6;
|
||||
address->in_addr.in6 = *a;
|
||||
address->prefixlen = prefixlen;
|
||||
address->prefixlen = 64;
|
||||
address->lifetime_preferred_usec = lifetime_preferred_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;
|
||||
|
||||
log_dhcp_pd_address(link, address);
|
||||
@ -489,20 +487,13 @@ static int dhcp_pd_get_preferred_subnet_prefix(
|
||||
"subnet id %" PRIu64 " is out of range. Only have %" PRIu64 " subnets.",
|
||||
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;
|
||||
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++) {
|
||||
/* If we do not have an allocation preference just iterate
|
||||
* through the address space and return the first free prefix. */
|
||||
@ -519,11 +510,16 @@ static int dhcp_pd_get_preferred_subnet_prefix(
|
||||
|
||||
/* Check that the prefix is not assigned to another link. */
|
||||
if (link_get_by_dhcp_pd_subnet_prefix(link->manager, &prefix, &assigned_link) < 0 ||
|
||||
assigned_link == link) {
|
||||
*ret = prefix;
|
||||
return 0;
|
||||
}
|
||||
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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dhcp_pd_assign_subnet_prefix(
|
||||
@ -531,7 +527,8 @@ static int dhcp_pd_assign_subnet_prefix(
|
||||
const struct in6_addr *pd_prefix,
|
||||
uint8_t pd_prefix_len,
|
||||
usec_t lifetime_preferred_usec,
|
||||
usec_t lifetime_valid_usec) {
|
||||
usec_t lifetime_valid_usec,
|
||||
bool is_uplink) {
|
||||
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
struct in6_addr prefix;
|
||||
@ -541,68 +538,31 @@ static int dhcp_pd_assign_subnet_prefix(
|
||||
assert(link->network);
|
||||
assert(pd_prefix);
|
||||
|
||||
if (dhcp_pd_get_assigned_subnet_prefix(link, pd_prefix, pd_prefix_len, &prefix) < 0 &&
|
||||
dhcp_pd_get_preferred_subnet_prefix(link, pd_prefix, pd_prefix_len, &prefix) < 0)
|
||||
return 0;
|
||||
r = dhcp_pd_get_preferred_subnet_prefix(link, pd_prefix, pd_prefix_len, &prefix);
|
||||
if (r < 0)
|
||||
return r == -ERANGE ? 0 : r;
|
||||
|
||||
(void) in6_addr_prefix_to_string(&prefix, 64, &buf);
|
||||
|
||||
if (link_radv_enabled(link) && link->network->dhcp_pd_announce) {
|
||||
r = radv_add_prefix(link, &prefix, 64, lifetime_preferred_usec, lifetime_valid_usec);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r,
|
||||
"Failed to assign/update prefix %s to IPv6 Router Advertisement: %m",
|
||||
strna(buf));
|
||||
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);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r,
|
||||
"Failed to assign/update prefix %s to IPv6 Router Advertisement: %m",
|
||||
strna(buf));
|
||||
}
|
||||
}
|
||||
|
||||
r = dhcp_pd_request_route(link, &prefix, 64, lifetime_valid_usec);
|
||||
r = dhcp_pd_request_route(link, &prefix, 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(
|
||||
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)
|
||||
return log_link_warning_errno(link, r,
|
||||
"Failed to assign/update route for prefix %s: %m",
|
||||
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)
|
||||
return log_link_warning_errno(link, r,
|
||||
"Failed to assign/update address for prefix %s: %m",
|
||||
@ -954,19 +914,15 @@ static int dhcp4_pd_assign_subnet_prefix(Link *link, Link *uplink) {
|
||||
return r;
|
||||
|
||||
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);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else {
|
||||
r = dhcp_pd_assign_subnet_prefix(link, &pd_prefix, pd_prefixlen, lifetime_usec, lifetime_usec);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = dhcp_pd_assign_subnet_prefix(link, &pd_prefix, pd_prefixlen, lifetime_usec, lifetime_usec, /* is_uplink = */ false);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
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_valid_usec = usec_add(lifetime_valid_sec * USEC_PER_SEC, timestamp_usec);
|
||||
|
||||
if (link == uplink)
|
||||
r = dhcp_pd_assign_prefix_on_uplink(link, &pd_prefix, pd_prefix_len, lifetime_preferred_usec, lifetime_valid_usec);
|
||||
else
|
||||
r = dhcp_pd_assign_subnet_prefix(link, &pd_prefix, pd_prefix_len, lifetime_preferred_usec, lifetime_valid_usec);
|
||||
r = dhcp_pd_assign_subnet_prefix(link, &pd_prefix, pd_prefix_len,
|
||||
lifetime_preferred_usec, lifetime_valid_usec,
|
||||
/* is_uplink = */ link == uplink);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include "alloc-util.h"
|
||||
#include "cgroup-setup.h"
|
||||
#include "cgroup-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "oomd-util.h"
|
||||
@ -13,6 +14,7 @@
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "tests.h"
|
||||
#include "tmpfile-util.h"
|
||||
|
||||
static int fork_and_sleep(unsigned sleep_min) {
|
||||
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) {
|
||||
_cleanup_(unlink_tempfilep) char path[] = "/oomdgetsysctxtestXXXXXX";
|
||||
_cleanup_close_ int fd = -1;
|
||||
OomdSystemContext ctx;
|
||||
|
||||
if (geteuid() != 0)
|
||||
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);
|
||||
|
||||
@ -283,7 +286,7 @@ static void test_oomd_system_context_acquire(void) {
|
||||
static void test_oomd_pressure_above(void) {
|
||||
_cleanup_hashmap_free_ Hashmap *h1 = NULL, *h2 = NULL;
|
||||
_cleanup_set_free_ Set *t1 = NULL, *t2 = NULL, *t3 = NULL;
|
||||
OomdCGroupContext ctx[2], *c;
|
||||
OomdCGroupContext ctx[2] = {}, *c;
|
||||
loadavg_t threshold;
|
||||
|
||||
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);
|
||||
ctx[1].mem_pressure_limit = threshold;
|
||||
|
||||
|
||||
/* High memory pressure */
|
||||
assert_se(h1 = hashmap_new(&string_hash_ops));
|
||||
assert_se(hashmap_put(h1, "/herp.slice", &ctx[0]) >= 0);
|
||||
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->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(hashmap_put(h2, "/derp.slice", &ctx[1]) >= 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->mem_pressure_limit_hit_start == 0);
|
||||
|
||||
/* High memory pressure w/ multiple cgroups */
|
||||
assert_se(hashmap_put(h1, "/derp.slice", &ctx[1]) >= 0);
|
||||
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(c = hashmap_get(h1, "/herp.slice"));
|
||||
assert_se(c->mem_pressure_limit_hit_start > 0);
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "log.h"
|
||||
#include "path-util.h"
|
||||
#include "string-util.h"
|
||||
@ -18,7 +19,10 @@
|
||||
static int watchdog_fd = -1;
|
||||
static char *watchdog_device;
|
||||
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 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
|
||||
* 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_GOV_NAME_MAXLEN 20 /* From the kernel watchdog driver */
|
||||
|
||||
static int saturated_usec_to_sec(usec_t val) {
|
||||
usec_t t = DIV_ROUND_UP(val, USEC_PER_SEC);
|
||||
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) {
|
||||
int flags = enable ? WDIOS_ENABLECARD : WDIOS_DISABLECARD;
|
||||
|
||||
@ -84,6 +149,46 @@ static int watchdog_set_timeout(void) {
|
||||
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) {
|
||||
assert(watchdog_fd >= 0);
|
||||
|
||||
@ -95,6 +200,60 @@ static int watchdog_ping_now(void) {
|
||||
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) {
|
||||
int r;
|
||||
|
||||
@ -121,6 +280,12 @@ static int update_timeout(void) {
|
||||
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);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -210,9 +375,38 @@ int watchdog_setup(usec_t timeout) {
|
||||
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;
|
||||
|
||||
/* 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());
|
||||
|
||||
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) {
|
||||
usec_t ntime;
|
||||
usec_t ntime, timeout;
|
||||
|
||||
if (watchdog_timeout == 0)
|
||||
return 0;
|
||||
@ -237,12 +431,13 @@ int watchdog_ping(void) {
|
||||
return open_watchdog();
|
||||
|
||||
ntime = now(clock_boottime_or_monotonic());
|
||||
timeout = calc_timeout();
|
||||
|
||||
/* 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)) {
|
||||
assert(ntime >= watchdog_last_ping);
|
||||
if ((ntime - watchdog_last_ping) < (watchdog_timeout / 4))
|
||||
if ((ntime - watchdog_last_ping) < (timeout / 4))
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -8,6 +8,8 @@
|
||||
|
||||
int watchdog_set_device(const char *path);
|
||||
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);
|
||||
void watchdog_close(bool disarm);
|
||||
usec_t watchdog_runtime_wait(void);
|
||||
|
||||
@ -29,10 +29,11 @@ static const char *arg_test_dir = NULL;
|
||||
|
||||
TEST(chase_symlinks) {
|
||||
_cleanup_free_ char *result = NULL;
|
||||
_cleanup_close_ int pfd = -1;
|
||||
char *temp;
|
||||
const char *top, *p, *pslash, *q, *qslash;
|
||||
struct stat st;
|
||||
int r, pfd;
|
||||
int r;
|
||||
|
||||
temp = strjoina(arg_test_dir ?: "/tmp", "/test-chase.XXXXXX");
|
||||
assert_se(mkdtemp(temp));
|
||||
@ -318,6 +319,7 @@ TEST(chase_symlinks) {
|
||||
assert_se(fstat(pfd, &st) >= 0);
|
||||
assert_se(S_ISLNK(st.st_mode));
|
||||
result = mfree(result);
|
||||
pfd = safe_close(pfd);
|
||||
|
||||
/* s1 -> s2 -> nonexistent */
|
||||
q = strjoina(temp, "/s1");
|
||||
@ -331,6 +333,7 @@ TEST(chase_symlinks) {
|
||||
assert_se(fstat(pfd, &st) >= 0);
|
||||
assert_se(S_ISLNK(st.st_mode));
|
||||
result = mfree(result);
|
||||
pfd = safe_close(pfd);
|
||||
|
||||
/* Test CHASE_STEP */
|
||||
|
||||
|
||||
@ -1,20 +1,23 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "psi-util.h"
|
||||
#include "tests.h"
|
||||
#include "tmpfile-util.h"
|
||||
|
||||
TEST(read_mem_pressure) {
|
||||
_cleanup_(unlink_tempfilep) char path[] = "/tmp/pressurereadtestXXXXXX";
|
||||
_cleanup_close_ int fd = -1;
|
||||
ResourcePressure rp;
|
||||
|
||||
if (geteuid() != 0)
|
||||
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(path, PRESSURE_TYPE_SOME, &rp) < 0);
|
||||
|
||||
@ -35,7 +35,7 @@ TEST(tmpfiles) {
|
||||
assert_se(endswith(ans, " (deleted)"));
|
||||
|
||||
fd2 = mkostemp_safe(pattern);
|
||||
assert_se(fd >= 0);
|
||||
assert_se(fd2 >= 0);
|
||||
assert_se(unlink(pattern) == 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");
|
||||
assert_se(tempfn_random(pattern, NULL, &d) >= 0);
|
||||
|
||||
fd = safe_close(fd);
|
||||
fd = open_tmpfile_linkable(d, O_RDWR|O_CLOEXEC, &tmp);
|
||||
assert_se(fd >= 0);
|
||||
assert_se(write(fd, "foobar\n", 7) == 7);
|
||||
|
||||
@ -737,6 +737,8 @@ LogLevel=
|
||||
LogLocation=
|
||||
LogTarget=
|
||||
RuntimeWatchdogSec=
|
||||
RuntimeWatchdogPreSec=
|
||||
RuntimeWatchdogPreGovernor=
|
||||
ShowStatus=
|
||||
RebootWatchdogSec=
|
||||
ShutdownWatchdogSec=
|
||||
|
||||
@ -10,7 +10,7 @@ DHCPPrefixDelegation=yes
|
||||
|
||||
[DHCPPrefixDelegation]
|
||||
UplinkInterface=veth99
|
||||
SubnetId=2
|
||||
SubnetId=0
|
||||
Announce=no
|
||||
Token=eui64
|
||||
Token=::1a:2b:3c:4d
|
||||
|
||||
@ -5269,11 +5269,11 @@ class NetworkdDHCPPDTests(unittest.TestCase, Utilities):
|
||||
# Link Subnet IDs
|
||||
# test1: 0x00
|
||||
# dummy97: 0x01 (The link will appear later)
|
||||
# dummy98: 0x02
|
||||
# dummy99: auto -> 0x03 (No address assignment)
|
||||
# dummy98: 0x00
|
||||
# dummy99: auto -> 0x02 (No address assignment)
|
||||
# veth97: 0x08
|
||||
# veth98: 0x09
|
||||
# veth99: 0x10 (ignored, as it is upstream)
|
||||
# veth99: 0x10
|
||||
|
||||
print('### 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
|
||||
self.assertRegex(output, 'inet6 3ffe:501:ffff:100::[0-9]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
|
||||
# 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)
|
||||
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')
|
||||
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)
|
||||
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)
|
||||
# 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')
|
||||
|
||||
print('### ip -6 address show dev dummy98 scope global')
|
||||
output = check_output('ip -6 address show dev dummy98 scope global')
|
||||
print(output)
|
||||
# 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)
|
||||
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')
|
||||
output = check_output('ip -6 address show dev dummy99 scope global')
|
||||
print(output)
|
||||
# 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')
|
||||
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')
|
||||
output = check_output('ip -6 route show dev veth99')
|
||||
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')
|
||||
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')
|
||||
output = check_output('ip -6 route show dev dummy98')
|
||||
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')
|
||||
output = check_output('ip -6 route show dev dummy99')
|
||||
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')
|
||||
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')
|
||||
print(output)
|
||||
# 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)
|
||||
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')
|
||||
output = check_output('ip -6 address show dev dummy99 scope global')
|
||||
print(output)
|
||||
# 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')
|
||||
output = check_output('ip -6 route show dev dummy98')
|
||||
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')
|
||||
output = check_output('ip -6 route show dev dummy99')
|
||||
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):
|
||||
print('### ip -4 address show dev veth-peer scope global')
|
||||
@ -5447,8 +5449,9 @@ class NetworkdDHCPPDTests(unittest.TestCase, Utilities):
|
||||
# Link Subnet IDs
|
||||
# test1: 0x00
|
||||
# dummy97: 0x01 (The link will appear later)
|
||||
# dummy98: 0x02
|
||||
# dummy99: auto -> 0x03 (No address assignment)
|
||||
# dummy98: 0x00
|
||||
# dummy99: auto -> 0x0[23] (No address assignment)
|
||||
# 6rd-XXX: auto -> 0x0[23]
|
||||
# veth97: 0x08
|
||||
# veth98: 0x09
|
||||
# veth99: 0x10
|
||||
@ -5481,15 +5484,15 @@ class NetworkdDHCPPDTests(unittest.TestCase, Utilities):
|
||||
output = check_output('ip -6 address show dev dummy98 scope global')
|
||||
print(output)
|
||||
# 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)
|
||||
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')
|
||||
output = check_output('ip -6 address show dev dummy99 scope global')
|
||||
print(output)
|
||||
# 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')
|
||||
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')
|
||||
output = check_output('ip -6 route show dev dummy98')
|
||||
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')
|
||||
output = check_output('ip -6 route show dev dummy99')
|
||||
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')
|
||||
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))
|
||||
output = check_output('ip -6 address show dev {}'.format(tunnel_name))
|
||||
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')
|
||||
|
||||
print('### ip -6 route show dev {}'.format(tunnel_name))
|
||||
output = check_output('ip -6 route show dev {}'.format(tunnel_name))
|
||||
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]*')
|
||||
|
||||
print('### ip -6 route show default')
|
||||
|
||||
@ -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
|
||||
|
||||
DefaultDependencies=no
|
||||
After=systemd-sysusers.service systemd-networkd.service
|
||||
After=systemd-sysusers.service
|
||||
Before=network.target nss-lookup.target shutdown.target
|
||||
Conflicts=shutdown.target
|
||||
Wants=nss-lookup.target
|
||||
|
||||
@ -22,4 +22,4 @@ After=swap.target
|
||||
What=tmpfs
|
||||
Where=/tmp
|
||||
Type=tmpfs
|
||||
Options=mode=1777,strictatime,nosuid,nodev,size=50%,nr_inodes=1m
|
||||
Options=mode=1777,strictatime,nosuid,nodev,size=50%%,nr_inodes=1m
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user