Compare commits
No commits in common. "097537f07a2fab3cb73aef7bc59f2a66aa93f533" and "6bbeef204252f15382d0b6cad60e37b9f879caa4" have entirely different histories.
097537f07a
...
6bbeef2042
|
@ -514,13 +514,6 @@ evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:*svnLENOVO:*pvrLenovoYoga500-14IBD*
|
||||||
EVDEV_ABS_35=117:3952:36
|
EVDEV_ABS_35=117:3952:36
|
||||||
EVDEV_ABS_36=105:1960:26
|
EVDEV_ABS_36=105:1960:26
|
||||||
|
|
||||||
# Lenovo Thinkpad T490
|
|
||||||
evdev:name:SynPS/2 Synaptics TouchPad:dmi:*:svnLENOVO:*pvrThinkPadT490:*
|
|
||||||
EVDEV_ABS_00=::57
|
|
||||||
EVDEV_ABS_01=::33
|
|
||||||
EVDEV_ABS_35=::57
|
|
||||||
EVDEV_ABS_36=::33
|
|
||||||
|
|
||||||
#########################################
|
#########################################
|
||||||
# Razer
|
# Razer
|
||||||
#########################################
|
#########################################
|
||||||
|
|
|
@ -835,11 +835,7 @@
|
||||||
container names may have a length up to 64 characters. As this option derives the host-side interface
|
container names may have a length up to 64 characters. As this option derives the host-side interface
|
||||||
name from the container name the name is possibly truncated. Thus, care needs to be taken to ensure
|
name from the container name the name is possibly truncated. Thus, care needs to be taken to ensure
|
||||||
that interface names remain unique in this case, or even better container names are generally not
|
that interface names remain unique in this case, or even better container names are generally not
|
||||||
chosen longer than 12 characters, to avoid the truncation. If the name is truncated,
|
chosen longer than 12 characters, to avoid the truncation. Alternatively, the
|
||||||
<command>systemd-nspawn</command> will automatically append a 4-digit hash value to the name to
|
|
||||||
reduce the chance of collisions. However, the hash algorithm is not collision-free. (See
|
|
||||||
<citerefentry><refentrytitle>systemd.net-naming-scheme</refentrytitle><manvolnum>7</manvolnum></citerefentry>
|
|
||||||
for details on older naming algorithms for this interface). Alternatively, the
|
|
||||||
<option>--network-veth-extra=</option> option may be used, which allows free configuration of the
|
<option>--network-veth-extra=</option> option may be used, which allows free configuration of the
|
||||||
host-side interface name independently of the container name — but might require a bit more
|
host-side interface name independently of the container name — but might require a bit more
|
||||||
additional configuration in case bridging in a fashion similar to <option>--network-bridge=</option>
|
additional configuration in case bridging in a fashion similar to <option>--network-bridge=</option>
|
||||||
|
|
|
@ -46,11 +46,6 @@
|
||||||
devices based on those properties. See the description of <varname>NamePolicy=</varname> and
|
devices based on those properties. See the description of <varname>NamePolicy=</varname> and
|
||||||
<varname>MACAddressPolicy=</varname> in
|
<varname>MACAddressPolicy=</varname> in
|
||||||
<citerefentry><refentrytitle>systemd.link</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
|
<citerefentry><refentrytitle>systemd.link</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
|
||||||
|
|
||||||
<para>Note that while the concept of network interface naming schemes is primarily relevant in the
|
|
||||||
context of <filename>systemd-udevd.service</filename>, the
|
|
||||||
<citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
|
||||||
container manager also takes it into account when naming network interfaces, see below.</para>
|
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
|
@ -334,21 +329,7 @@
|
||||||
<para>Previously two-letter interface type prefix was prepended to
|
<para>Previously two-letter interface type prefix was prepended to
|
||||||
<varname>ID_NET_LABEL_ONBOARD=</varname>. This is not done anymore.</para></listitem>
|
<varname>ID_NET_LABEL_ONBOARD=</varname>. This is not done anymore.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
<varlistentry>
|
|
||||||
<term><constant>v245</constant></term>
|
|
||||||
|
|
||||||
<listitem><para>When
|
|
||||||
<citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
|
||||||
derives the name for the host side of the network interface created with
|
|
||||||
<option>--network-veth</option> from the container name it previously simply truncated the result
|
|
||||||
at 15 characters if longer (since that's the maximum length for network interface names). From now
|
|
||||||
on, for any interface name that would be longer than 15 characters the last 4 characters are set to
|
|
||||||
a 24bit hash value of the full interface name. This way network interface name collisions between
|
|
||||||
multiple similarly named containers (who only differ in container name suffix) should be less
|
|
||||||
likely (but still possible, since the 24bit hash value is very small).</para></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
|
|
||||||
<para>Note that <constant>latest</constant> may be used to denote the latest scheme known (to this
|
<para>Note that <constant>latest</constant> may be used to denote the latest scheme known (to this
|
||||||
particular version of systemd.</para>
|
particular version of systemd.</para>
|
||||||
|
@ -447,8 +428,7 @@ ID_NET_NAME_PATH=encf5f0</programlisting>
|
||||||
<para>
|
<para>
|
||||||
<citerefentry><refentrytitle>udev</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
|
<citerefentry><refentrytitle>udev</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
|
||||||
<citerefentry><refentrytitle>udevadm</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
<citerefentry><refentrytitle>udevadm</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||||
<ulink url="https://systemd.io/PREDICTABLE_INTERFACE_NAMES">Predictable Network Interface Names</ulink>,
|
<ulink url="https://systemd.io/PREDICTABLE_INTERFACE_NAMES">Predictable Network Interface Names</ulink>
|
||||||
<citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
|
|
@ -1378,16 +1378,6 @@
|
||||||
service type to CS6 (network control) or CS4 (Realtime). Defaults to CS6.</para>
|
service type to CS6 (network control) or CS4 (Realtime). Defaults to CS6.</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
<varlistentry>
|
|
||||||
<term><varname>MultiPathRoute=<replaceable>address</replaceable>[@<replaceable>name</replaceable>] [<replaceable>weight</replaceable>]</varname></term>
|
|
||||||
<listitem>
|
|
||||||
<para>Configures multipath route. Multipath routing is the technique of using multiple
|
|
||||||
alternative paths through a network. Takes gateway address. Optionally, takes a network
|
|
||||||
interface name or index separated with <literal>@</literal>, and a weight in 1..256 for
|
|
||||||
this multipath route separated with whitespace. This setting can be specified multiple
|
|
||||||
times. If an empty string is assigned, then the all previous assignments are cleared.</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
|
|
@ -45,16 +45,17 @@ w+ /file/to/append-to - - - - conte
|
||||||
d /directory/to/create-and-cleanup mode user group cleanup-age -
|
d /directory/to/create-and-cleanup mode user group cleanup-age -
|
||||||
D /directory/to/create-and-remove mode user group cleanup-age -
|
D /directory/to/create-and-remove mode user group cleanup-age -
|
||||||
e /directory/to/cleanup mode user group cleanup-age -
|
e /directory/to/cleanup mode user group cleanup-age -
|
||||||
|
v /subvolume/to/create mode user group - -
|
||||||
v /subvolume-or-directory/to/create mode user group - -
|
v /subvolume-or-directory/to/create mode user group - -
|
||||||
Q /subvolume/to/create mode user group - -
|
Q /subvolume/to/create mode user group - -
|
||||||
p /fifo/to/create mode user group - -
|
p /fifo/to/create mode user group - -
|
||||||
p+ /fifo/to/[re]create mode user group - -
|
p+ /fifo/to/[re]create mode user group - -
|
||||||
L /symlink/to/create - - - - symlink/target/path
|
L /symlink/to/create - - - - symlink/target/path
|
||||||
L+ /symlink/to/[re]create - - - - symlink/target/path
|
L+ /symlink/to/[re]create - - - - symlink/target/path
|
||||||
c /dev/char-device-to-create mode user group - major:minor
|
c /dev/char-device-to-create mode user group - -
|
||||||
c+ /dev/char-device-to-[re]create mode user group - major:minor
|
c+ /dev/char-device-to-[re]create mode user group - -
|
||||||
b /dev/block-device-to-create mode user group - major:minor
|
b /dev/block-device-to-create mode user group - -
|
||||||
b+ /dev/block-device-to-[re]create mode user group - major:minor
|
b+ /dev/block-device-to-[re]create mode user group - -
|
||||||
C /target/to/create - - - - /source/to/copy
|
C /target/to/create - - - - /source/to/copy
|
||||||
x /path-or-glob/to/ignore - - - - -
|
x /path-or-glob/to/ignore - - - - -
|
||||||
X /path-or-glob/to/ignore/recursively - - - - -
|
X /path-or-glob/to/ignore/recursively - - - - -
|
||||||
|
|
|
@ -383,62 +383,25 @@ JobType job_type_lookup_merge(JobType a, JobType b) {
|
||||||
return job_merging_table[(a - 1) * a / 2 + b];
|
return job_merging_table[(a - 1) * a / 2 + b];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool job_later_link_matters(Job *j, JobType type, unsigned generation) {
|
bool job_type_is_redundant(JobType a, UnitActiveState b) {
|
||||||
JobDependency *l;
|
switch (a) {
|
||||||
|
|
||||||
assert(j);
|
|
||||||
|
|
||||||
j->generation = generation;
|
|
||||||
|
|
||||||
LIST_FOREACH(subject, l, j->subject_list) {
|
|
||||||
UnitActiveState state = _UNIT_ACTIVE_STATE_INVALID;
|
|
||||||
|
|
||||||
/* Have we seen this before? */
|
|
||||||
if (l->object->generation == generation)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
state = unit_active_state(l->object->unit);
|
|
||||||
switch (type) {
|
|
||||||
|
|
||||||
case JOB_START:
|
|
||||||
return IN_SET(state, UNIT_INACTIVE, UNIT_FAILED) ||
|
|
||||||
job_later_link_matters(l->object, type, generation);
|
|
||||||
|
|
||||||
case JOB_STOP:
|
|
||||||
return IN_SET(state, UNIT_ACTIVE, UNIT_RELOADING) ||
|
|
||||||
job_later_link_matters(l->object, type, generation);
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert_not_reached("Invalid job type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool job_is_redundant(Job *j, unsigned generation) {
|
|
||||||
|
|
||||||
assert(j);
|
|
||||||
|
|
||||||
UnitActiveState state = unit_active_state(j->unit);
|
|
||||||
switch (j->type) {
|
|
||||||
|
|
||||||
case JOB_START:
|
case JOB_START:
|
||||||
return IN_SET(state, UNIT_ACTIVE, UNIT_RELOADING) && !job_later_link_matters(j, JOB_START, generation);
|
return IN_SET(b, UNIT_ACTIVE, UNIT_RELOADING);
|
||||||
|
|
||||||
case JOB_STOP:
|
case JOB_STOP:
|
||||||
return IN_SET(state, UNIT_INACTIVE, UNIT_FAILED) && !job_later_link_matters(j, JOB_STOP, generation);
|
return IN_SET(b, UNIT_INACTIVE, UNIT_FAILED);
|
||||||
|
|
||||||
case JOB_VERIFY_ACTIVE:
|
case JOB_VERIFY_ACTIVE:
|
||||||
return IN_SET(state, UNIT_ACTIVE, UNIT_RELOADING);
|
return IN_SET(b, UNIT_ACTIVE, UNIT_RELOADING);
|
||||||
|
|
||||||
case JOB_RELOAD:
|
case JOB_RELOAD:
|
||||||
return
|
return
|
||||||
state == UNIT_RELOADING;
|
b == UNIT_RELOADING;
|
||||||
|
|
||||||
case JOB_RESTART:
|
case JOB_RESTART:
|
||||||
return
|
return
|
||||||
state == UNIT_ACTIVATING;
|
b == UNIT_ACTIVATING;
|
||||||
|
|
||||||
case JOB_NOP:
|
case JOB_NOP:
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -196,8 +196,7 @@ _pure_ static inline bool job_type_is_superset(JobType a, JobType b) {
|
||||||
return a == job_type_lookup_merge(a, b);
|
return a == job_type_lookup_merge(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool job_later_link_matters(Job *j, JobType type, unsigned generation);
|
bool job_type_is_redundant(JobType a, UnitActiveState b) _pure_;
|
||||||
bool job_is_redundant(Job *j, unsigned generation);
|
|
||||||
|
|
||||||
/* Collapses a state-dependent job type into a simpler type by observing
|
/* Collapses a state-dependent job type into a simpler type by observing
|
||||||
* the state of the unit which it is going to be applied to. */
|
* the state of the unit which it is going to be applied to. */
|
||||||
|
|
|
@ -279,7 +279,7 @@ static int transaction_merge_jobs(Transaction *tr, sd_bus_error *e) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void transaction_drop_redundant(Transaction *tr, unsigned generation) {
|
static void transaction_drop_redundant(Transaction *tr) {
|
||||||
bool again;
|
bool again;
|
||||||
|
|
||||||
/* Goes through the transaction and removes all jobs of the units whose jobs are all noops. If not
|
/* Goes through the transaction and removes all jobs of the units whose jobs are all noops. If not
|
||||||
|
@ -299,7 +299,7 @@ static void transaction_drop_redundant(Transaction *tr, unsigned generation) {
|
||||||
|
|
||||||
LIST_FOREACH(transaction, k, j)
|
LIST_FOREACH(transaction, k, j)
|
||||||
if (tr->anchor_job == k ||
|
if (tr->anchor_job == k ||
|
||||||
!job_is_redundant(k, generation) ||
|
!job_type_is_redundant(k->type, unit_active_state(k->unit)) ||
|
||||||
(k->unit->job && job_type_is_conflicting(k->type, k->unit->job->type))) {
|
(k->unit->job && job_type_is_conflicting(k->type, k->unit->job->type))) {
|
||||||
keep = true;
|
keep = true;
|
||||||
break;
|
break;
|
||||||
|
@ -730,7 +730,7 @@ int transaction_activate(
|
||||||
transaction_minimize_impact(tr);
|
transaction_minimize_impact(tr);
|
||||||
|
|
||||||
/* Third step: Drop redundant jobs */
|
/* Third step: Drop redundant jobs */
|
||||||
transaction_drop_redundant(tr, generation++);
|
transaction_drop_redundant(tr);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/* Fourth step: Let's remove unneeded jobs that might
|
/* Fourth step: Let's remove unneeded jobs that might
|
||||||
|
@ -772,7 +772,7 @@ int transaction_activate(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Eights step: Drop redundant jobs again, if the merging now allows us to drop more. */
|
/* Eights step: Drop redundant jobs again, if the merging now allows us to drop more. */
|
||||||
transaction_drop_redundant(tr, generation++);
|
transaction_drop_redundant(tr);
|
||||||
|
|
||||||
/* Ninth step: check whether we can actually apply this */
|
/* Ninth step: check whether we can actually apply this */
|
||||||
r = transaction_is_destructive(tr, mode, e);
|
r = transaction_is_destructive(tr, mode, e);
|
||||||
|
|
|
@ -142,9 +142,11 @@ int sd_netlink_message_is_broadcast(const sd_netlink_message *m) {
|
||||||
/* If successful the updated message will be correctly aligned, if
|
/* If successful the updated message will be correctly aligned, if
|
||||||
unsuccessful the old message is untouched. */
|
unsuccessful the old message is untouched. */
|
||||||
static int add_rtattr(sd_netlink_message *m, unsigned short type, const void *data, size_t data_length) {
|
static int add_rtattr(sd_netlink_message *m, unsigned short type, const void *data, size_t data_length) {
|
||||||
size_t message_length;
|
uint32_t rta_length;
|
||||||
|
size_t message_length, padding_length;
|
||||||
struct nlmsghdr *new_hdr;
|
struct nlmsghdr *new_hdr;
|
||||||
struct rtattr *rta;
|
struct rtattr *rta;
|
||||||
|
char *padding;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
int offset;
|
int offset;
|
||||||
|
|
||||||
|
@ -152,10 +154,16 @@ static int add_rtattr(sd_netlink_message *m, unsigned short type, const void *da
|
||||||
assert(m->hdr);
|
assert(m->hdr);
|
||||||
assert(!m->sealed);
|
assert(!m->sealed);
|
||||||
assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
|
assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
|
||||||
assert(!data || data_length > 0);
|
assert(!data || data_length);
|
||||||
|
|
||||||
|
/* get offset of the new attribute */
|
||||||
|
offset = m->hdr->nlmsg_len;
|
||||||
|
|
||||||
|
/* get the size of the new rta attribute (with padding at the end) */
|
||||||
|
rta_length = RTA_LENGTH(data_length);
|
||||||
|
|
||||||
/* get the new message size (with padding at the end) */
|
/* get the new message size (with padding at the end) */
|
||||||
message_length = m->hdr->nlmsg_len + RTA_SPACE(data_length);
|
message_length = offset + RTA_ALIGN(rta_length);
|
||||||
|
|
||||||
/* buffer should be smaller than both one page or 8K to be accepted by the kernel */
|
/* buffer should be smaller than both one page or 8K to be accepted by the kernel */
|
||||||
if (message_length > MIN(page_size(), 8192UL))
|
if (message_length > MIN(page_size(), 8192UL))
|
||||||
|
@ -168,19 +176,33 @@ static int add_rtattr(sd_netlink_message *m, unsigned short type, const void *da
|
||||||
m->hdr = new_hdr;
|
m->hdr = new_hdr;
|
||||||
|
|
||||||
/* get pointer to the attribute we are about to add */
|
/* get pointer to the attribute we are about to add */
|
||||||
rta = (struct rtattr *) ((uint8_t *) m->hdr + m->hdr->nlmsg_len);
|
rta = (struct rtattr *) ((uint8_t *) m->hdr + offset);
|
||||||
|
|
||||||
rtattr_append_attribute_internal(rta, type, data, data_length);
|
|
||||||
|
|
||||||
/* if we are inside containers, extend them */
|
/* if we are inside containers, extend them */
|
||||||
for (i = 0; i < m->n_containers; i++)
|
for (i = 0; i < m->n_containers; i++)
|
||||||
GET_CONTAINER(m, i)->rta_len += RTA_SPACE(data_length);
|
GET_CONTAINER(m, i)->rta_len += message_length - offset;
|
||||||
|
|
||||||
|
/* fill in the attribute */
|
||||||
|
rta->rta_type = type;
|
||||||
|
rta->rta_len = rta_length;
|
||||||
|
if (data)
|
||||||
|
/* we don't deal with the case where the user lies about the type
|
||||||
|
* and gives us too little data (so don't do that)
|
||||||
|
*/
|
||||||
|
padding = mempcpy(RTA_DATA(rta), data, data_length);
|
||||||
|
|
||||||
|
else
|
||||||
|
/* if no data was passed, make sure we still initialize the padding
|
||||||
|
note that we can have data_length > 0 (used by some containers) */
|
||||||
|
padding = RTA_DATA(rta);
|
||||||
|
|
||||||
|
/* make sure also the padding at the end of the message is initialized */
|
||||||
|
padding_length = (uint8_t*)m->hdr + message_length - (uint8_t*)padding;
|
||||||
|
memzero(padding, padding_length);
|
||||||
|
|
||||||
/* update message size */
|
/* update message size */
|
||||||
offset = m->hdr->nlmsg_len;
|
|
||||||
m->hdr->nlmsg_len = message_length;
|
m->hdr->nlmsg_len = message_length;
|
||||||
|
|
||||||
/* return old message size */
|
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
#include "sd-netlink.h"
|
#include "sd-netlink.h"
|
||||||
|
|
||||||
#include "memory-util.h"
|
|
||||||
#include "netlink-internal.h"
|
#include "netlink-internal.h"
|
||||||
#include "netlink-util.h"
|
#include "netlink-util.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
|
@ -179,60 +178,3 @@ int rtnl_log_parse_error(int r) {
|
||||||
int rtnl_log_create_error(int r) {
|
int rtnl_log_create_error(int r) {
|
||||||
return log_error_errno(r, "Failed to create netlink message: %m");
|
return log_error_errno(r, "Failed to create netlink message: %m");
|
||||||
}
|
}
|
||||||
|
|
||||||
void rtattr_append_attribute_internal(struct rtattr *rta, unsigned short type, const void *data, size_t data_length) {
|
|
||||||
size_t padding_length;
|
|
||||||
char *padding;
|
|
||||||
|
|
||||||
assert(rta);
|
|
||||||
assert(!data || data_length > 0);
|
|
||||||
|
|
||||||
/* fill in the attribute */
|
|
||||||
rta->rta_type = type;
|
|
||||||
rta->rta_len = RTA_LENGTH(data_length);
|
|
||||||
if (data)
|
|
||||||
/* we don't deal with the case where the user lies about the type
|
|
||||||
* and gives us too little data (so don't do that)
|
|
||||||
*/
|
|
||||||
padding = mempcpy(RTA_DATA(rta), data, data_length);
|
|
||||||
|
|
||||||
else
|
|
||||||
/* if no data was passed, make sure we still initialize the padding
|
|
||||||
note that we can have data_length > 0 (used by some containers) */
|
|
||||||
padding = RTA_DATA(rta);
|
|
||||||
|
|
||||||
/* make sure also the padding at the end of the message is initialized */
|
|
||||||
padding_length = (char *) rta + RTA_SPACE(data_length) - padding;
|
|
||||||
memzero(padding, padding_length);
|
|
||||||
}
|
|
||||||
|
|
||||||
int rtattr_append_attribute(struct rtattr **rta, unsigned short type, const void *data, size_t data_length) {
|
|
||||||
struct rtattr *new_rta, *sub_rta;
|
|
||||||
size_t message_length;
|
|
||||||
|
|
||||||
assert(rta);
|
|
||||||
assert(!data || data_length > 0);
|
|
||||||
|
|
||||||
/* get the new message size (with padding at the end) */
|
|
||||||
message_length = RTA_ALIGN(rta ? (*rta)->rta_len : 0) + RTA_SPACE(data_length);
|
|
||||||
|
|
||||||
/* buffer should be smaller than both one page or 8K to be accepted by the kernel */
|
|
||||||
if (message_length > MIN(page_size(), 8192UL))
|
|
||||||
return -ENOBUFS;
|
|
||||||
|
|
||||||
/* realloc to fit the new attribute */
|
|
||||||
new_rta = realloc(*rta, message_length);
|
|
||||||
if (!new_rta)
|
|
||||||
return -ENOMEM;
|
|
||||||
*rta = new_rta;
|
|
||||||
|
|
||||||
/* get pointer to the attribute we are about to add */
|
|
||||||
sub_rta = (struct rtattr *) ((uint8_t *) *rta + RTA_ALIGN((*rta)->rta_len));
|
|
||||||
|
|
||||||
rtattr_append_attribute_internal(sub_rta, type, data, data_length);
|
|
||||||
|
|
||||||
/* update rta_len */
|
|
||||||
(*rta)->rta_len = message_length;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
|
@ -77,6 +77,3 @@ int rtnl_log_create_error(int r);
|
||||||
|
|
||||||
int netlink_message_append_in_addr_union(sd_netlink_message *m, unsigned short type, int family, const union in_addr_union *data);
|
int netlink_message_append_in_addr_union(sd_netlink_message *m, unsigned short type, int family, const union in_addr_union *data);
|
||||||
int netlink_message_append_sockaddr_union(sd_netlink_message *m, unsigned short type, const union sockaddr_union *data);
|
int netlink_message_append_sockaddr_union(sd_netlink_message *m, unsigned short type, const union sockaddr_union *data);
|
||||||
|
|
||||||
void rtattr_append_attribute_internal(struct rtattr *rta, unsigned short type, const void *data, size_t data_length);
|
|
||||||
int rtattr_append_attribute(struct rtattr **rta, unsigned short type, const void *data, size_t data_length);
|
|
||||||
|
|
|
@ -1040,7 +1040,7 @@ int link_request_set_routes(Link *link) {
|
||||||
for (phase = 0; phase < _PHASE_MAX; phase++)
|
for (phase = 0; phase < _PHASE_MAX; phase++)
|
||||||
LIST_FOREACH(routes, rt, link->network->static_routes) {
|
LIST_FOREACH(routes, rt, link->network->static_routes) {
|
||||||
|
|
||||||
if ((in_addr_is_null(rt->family, &rt->gw) && ordered_set_isempty(rt->multipath_routes)) != (phase == PHASE_NON_GATEWAY))
|
if (in_addr_is_null(rt->family, &rt->gw) != (phase == PHASE_NON_GATEWAY))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
r = route_configure(rt, link, route_handler);
|
r = route_configure(rt, link, route_handler);
|
||||||
|
|
|
@ -147,7 +147,6 @@ Route.InitialAdvertisedReceiveWindow, config_parse_tcp_window,
|
||||||
Route.QuickAck, config_parse_quickack, 0, 0
|
Route.QuickAck, config_parse_quickack, 0, 0
|
||||||
Route.FastOpenNoCookie, config_parse_fast_open_no_cookie, 0, 0
|
Route.FastOpenNoCookie, config_parse_fast_open_no_cookie, 0, 0
|
||||||
Route.TTLPropagate, config_parse_route_ttl_propagate, 0, 0
|
Route.TTLPropagate, config_parse_route_ttl_propagate, 0, 0
|
||||||
Route.MultiPathRoute, config_parse_multipath_route, 0, 0
|
|
||||||
NextHop.Id, config_parse_nexthop_id, 0, 0
|
NextHop.Id, config_parse_nexthop_id, 0, 0
|
||||||
NextHop.Gateway, config_parse_nexthop_gateway, 0, 0
|
NextHop.Gateway, config_parse_nexthop_gateway, 0, 0
|
||||||
DHCPv4.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier)
|
DHCPv4.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier)
|
||||||
|
|
|
@ -144,8 +144,6 @@ void route_free(Route *route) {
|
||||||
set_remove(route->link->routes_foreign, route);
|
set_remove(route->link->routes_foreign, route);
|
||||||
}
|
}
|
||||||
|
|
||||||
ordered_set_free_free(route->multipath_routes);
|
|
||||||
|
|
||||||
sd_event_source_unref(route->expire);
|
sd_event_source_unref(route->expire);
|
||||||
|
|
||||||
free(route);
|
free(route);
|
||||||
|
@ -518,88 +516,6 @@ int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int append_nexthop_one(Route *route, MultipathRoute *m, struct rtattr **rta, size_t offset) {
|
|
||||||
struct rtnexthop *rtnh;
|
|
||||||
struct rtattr *new_rta;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(route);
|
|
||||||
assert(m);
|
|
||||||
assert(rta);
|
|
||||||
assert(*rta);
|
|
||||||
|
|
||||||
new_rta = realloc(*rta, RTA_ALIGN((*rta)->rta_len) + RTA_SPACE(sizeof(struct rtnexthop)));
|
|
||||||
if (!new_rta)
|
|
||||||
return -ENOMEM;
|
|
||||||
*rta = new_rta;
|
|
||||||
|
|
||||||
rtnh = (struct rtnexthop *)((uint8_t *) *rta + offset);
|
|
||||||
*rtnh = (struct rtnexthop) {
|
|
||||||
.rtnh_len = sizeof(*rtnh),
|
|
||||||
.rtnh_ifindex = m->ifindex,
|
|
||||||
.rtnh_hops = m->weight > 0 ? m->weight - 1 : 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
(*rta)->rta_len += sizeof(struct rtnexthop);
|
|
||||||
|
|
||||||
if (route->family == m->gateway.family) {
|
|
||||||
r = rtattr_append_attribute(rta, RTA_GATEWAY, &m->gateway.address, FAMILY_ADDRESS_SIZE(m->gateway.family));
|
|
||||||
if (r < 0)
|
|
||||||
goto clear;
|
|
||||||
rtnh = (struct rtnexthop *)((uint8_t *) *rta + offset);
|
|
||||||
rtnh->rtnh_len += RTA_SPACE(FAMILY_ADDRESS_SIZE(m->gateway.family));
|
|
||||||
} else {
|
|
||||||
r = rtattr_append_attribute(rta, RTA_VIA, &m->gateway, FAMILY_ADDRESS_SIZE(m->gateway.family) + sizeof(m->gateway.family));
|
|
||||||
if (r < 0)
|
|
||||||
goto clear;
|
|
||||||
rtnh = (struct rtnexthop *)((uint8_t *) *rta + offset);
|
|
||||||
rtnh->rtnh_len += RTA_SPACE(FAMILY_ADDRESS_SIZE(m->gateway.family) + sizeof(m->gateway.family));
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
clear:
|
|
||||||
(*rta)->rta_len -= sizeof(struct rtnexthop);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int append_nexthops(Route *route, sd_netlink_message *req) {
|
|
||||||
_cleanup_free_ struct rtattr *rta = NULL;
|
|
||||||
struct rtnexthop *rtnh;
|
|
||||||
MultipathRoute *m;
|
|
||||||
size_t offset;
|
|
||||||
Iterator i;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
if (ordered_set_isempty(route->multipath_routes))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
rta = new(struct rtattr, 1);
|
|
||||||
if (!rta)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
*rta = (struct rtattr) {
|
|
||||||
.rta_type = RTA_MULTIPATH,
|
|
||||||
.rta_len = RTA_LENGTH(0),
|
|
||||||
};
|
|
||||||
offset = (uint8_t *) RTA_DATA(rta) - (uint8_t *) rta;
|
|
||||||
|
|
||||||
ORDERED_SET_FOREACH(m, route->multipath_routes, i) {
|
|
||||||
r = append_nexthop_one(route, m, &rta, offset);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
rtnh = (struct rtnexthop *)((uint8_t *) rta + offset);
|
|
||||||
offset = (uint8_t *) RTNH_NEXT(rtnh) - (uint8_t *) rta;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = sd_netlink_message_append_data(req, RTA_MULTIPATH, RTA_DATA(rta), RTA_PAYLOAD(rta));
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int route_configure(
|
int route_configure(
|
||||||
Route *route,
|
Route *route,
|
||||||
Link *link,
|
Link *link,
|
||||||
|
@ -783,10 +699,6 @@ int route_configure(
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not append RTA_METRICS attribute: %m");
|
return log_link_error_errno(link, r, "Could not append RTA_METRICS attribute: %m");
|
||||||
|
|
||||||
r = append_nexthops(route, req);
|
|
||||||
if (r < 0)
|
|
||||||
return log_link_error_errno(link, r, "Could not append RTA_MULTIPATH attribute: %m");
|
|
||||||
|
|
||||||
r = netlink_call_async(link->manager->rtnl, NULL, req, callback,
|
r = netlink_call_async(link->manager->rtnl, NULL, req, callback,
|
||||||
link_netlink_destroy_callback, link);
|
link_netlink_destroy_callback, link);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
@ -1568,113 +1480,6 @@ int config_parse_route_ttl_propagate(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int config_parse_multipath_route(
|
|
||||||
const char *unit,
|
|
||||||
const char *filename,
|
|
||||||
unsigned line,
|
|
||||||
const char *section,
|
|
||||||
unsigned section_line,
|
|
||||||
const char *lvalue,
|
|
||||||
int ltype,
|
|
||||||
const char *rvalue,
|
|
||||||
void *data,
|
|
||||||
void *userdata) {
|
|
||||||
|
|
||||||
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
|
|
||||||
_cleanup_free_ char *word = NULL, *buf = NULL;
|
|
||||||
_cleanup_free_ MultipathRoute *m = NULL;
|
|
||||||
Network *network = userdata;
|
|
||||||
const char *p, *ip, *dev;
|
|
||||||
union in_addr_union a;
|
|
||||||
int family, r;
|
|
||||||
|
|
||||||
assert(filename);
|
|
||||||
assert(section);
|
|
||||||
assert(lvalue);
|
|
||||||
assert(rvalue);
|
|
||||||
assert(data);
|
|
||||||
|
|
||||||
r = route_new_static(network, filename, section_line, &n);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (isempty(rvalue)) {
|
|
||||||
n->multipath_routes = ordered_set_free_free(n->multipath_routes);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
m = new0(MultipathRoute, 1);
|
|
||||||
if (!m)
|
|
||||||
return log_oom();
|
|
||||||
|
|
||||||
p = rvalue;
|
|
||||||
r = extract_first_word(&p, &word, NULL, 0);
|
|
||||||
if (r == -ENOMEM)
|
|
||||||
return log_oom();
|
|
||||||
if (r <= 0) {
|
|
||||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
|
||||||
"Invalid multipath route option, ignoring assignment: %s", rvalue);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev = strchr(word, '@');
|
|
||||||
if (dev) {
|
|
||||||
buf = strndup(word, dev - word);
|
|
||||||
if (!buf)
|
|
||||||
return log_oom();
|
|
||||||
ip = buf;
|
|
||||||
dev++;
|
|
||||||
} else
|
|
||||||
ip = word;
|
|
||||||
|
|
||||||
r = in_addr_from_string_auto(ip, &family, &a);
|
|
||||||
if (r < 0) {
|
|
||||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
|
||||||
"Invalid multipath route gateway '%s', ignoring assignment: %m", rvalue);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
m->gateway.address = a;
|
|
||||||
m->gateway.family = family;
|
|
||||||
|
|
||||||
if (dev) {
|
|
||||||
r = parse_ifindex_or_ifname(dev, &m->ifindex);
|
|
||||||
if (r < 0) {
|
|
||||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
|
||||||
"Invalid interface name or index, ignoring assignment: %s", dev);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isempty(p)) {
|
|
||||||
r = safe_atou32(p, &m->weight);
|
|
||||||
if (r < 0) {
|
|
||||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
|
||||||
"Invalid multipath route weight, ignoring assignment: %s", p);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (m->weight == 0 || m->weight > 256) {
|
|
||||||
log_syntax(unit, LOG_ERR, filename, line, 0,
|
|
||||||
"Invalid multipath route weight, ignoring assignment: %s", p);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r = ordered_set_ensure_allocated(&n->multipath_routes, NULL);
|
|
||||||
if (r < 0)
|
|
||||||
return log_oom();
|
|
||||||
|
|
||||||
r = ordered_set_put(n->multipath_routes, m);
|
|
||||||
if (r < 0) {
|
|
||||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
|
||||||
"Failed to store multipath route, ignoring assignment: %m");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
TAKE_PTR(m);
|
|
||||||
TAKE_PTR(n);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int route_section_verify(Route *route, Network *network) {
|
int route_section_verify(Route *route, Network *network) {
|
||||||
if (section_is_invalid(route->section))
|
if (section_is_invalid(route->section))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
@ -10,17 +10,6 @@ typedef struct NetworkConfigSection NetworkConfigSection;
|
||||||
#include "networkd-network.h"
|
#include "networkd-network.h"
|
||||||
#include "networkd-util.h"
|
#include "networkd-util.h"
|
||||||
|
|
||||||
typedef struct MultipathRouteVia {
|
|
||||||
uint16_t family;
|
|
||||||
union in_addr_union address;
|
|
||||||
} _packed_ MultipathRouteVia;
|
|
||||||
|
|
||||||
typedef struct MultipathRoute {
|
|
||||||
MultipathRouteVia gateway;
|
|
||||||
int ifindex;
|
|
||||||
uint32_t weight;
|
|
||||||
} MultipathRoute;
|
|
||||||
|
|
||||||
struct Route {
|
struct Route {
|
||||||
Network *network;
|
Network *network;
|
||||||
NetworkConfigSection *section;
|
NetworkConfigSection *section;
|
||||||
|
@ -53,7 +42,6 @@ struct Route {
|
||||||
union in_addr_union dst;
|
union in_addr_union dst;
|
||||||
union in_addr_union src;
|
union in_addr_union src;
|
||||||
union in_addr_union prefsrc;
|
union in_addr_union prefsrc;
|
||||||
OrderedSet *multipath_routes;
|
|
||||||
|
|
||||||
usec_t lifetime;
|
usec_t lifetime;
|
||||||
sd_event_source *expire;
|
sd_event_source *expire;
|
||||||
|
@ -108,4 +96,3 @@ CONFIG_PARSER_PROTOTYPE(config_parse_quickack);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_fast_open_no_cookie);
|
CONFIG_PARSER_PROTOTYPE(config_parse_fast_open_no_cookie);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_route_ttl_propagate);
|
CONFIG_PARSER_PROTOTYPE(config_parse_route_ttl_propagate);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_route_mtu);
|
CONFIG_PARSER_PROTOTYPE(config_parse_route_mtu);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_multipath_route);
|
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
#include "ether-addr-util.h"
|
#include "ether-addr-util.h"
|
||||||
#include "lockfile-util.h"
|
#include "lockfile-util.h"
|
||||||
#include "missing_network.h"
|
#include "missing_network.h"
|
||||||
#include "netif-naming-scheme.h"
|
|
||||||
#include "netlink-util.h"
|
#include "netlink-util.h"
|
||||||
#include "nspawn-network.h"
|
#include "nspawn-network.h"
|
||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
|
@ -28,7 +27,6 @@
|
||||||
#define VETH_EXTRA_HOST_HASH_KEY SD_ID128_MAKE(48,c7,f6,b7,ea,9d,4c,9e,b7,28,d4,de,91,d5,bf,66)
|
#define VETH_EXTRA_HOST_HASH_KEY SD_ID128_MAKE(48,c7,f6,b7,ea,9d,4c,9e,b7,28,d4,de,91,d5,bf,66)
|
||||||
#define VETH_EXTRA_CONTAINER_HASH_KEY SD_ID128_MAKE(af,50,17,61,ce,f9,4d,35,84,0d,2b,20,54,be,ce,59)
|
#define VETH_EXTRA_CONTAINER_HASH_KEY SD_ID128_MAKE(af,50,17,61,ce,f9,4d,35,84,0d,2b,20,54,be,ce,59)
|
||||||
#define MACVLAN_HASH_KEY SD_ID128_MAKE(00,13,6d,bc,66,83,44,81,bb,0c,f9,51,1f,24,a6,6f)
|
#define MACVLAN_HASH_KEY SD_ID128_MAKE(00,13,6d,bc,66,83,44,81,bb,0c,f9,51,1f,24,a6,6f)
|
||||||
#define SHORTEN_IFNAME_HASH_KEY SD_ID128_MAKE(e1,90,a4,04,a8,ef,4b,51,8c,cc,c3,3a,9f,11,fc,a2)
|
|
||||||
|
|
||||||
static int remove_one_link(sd_netlink *rtnl, const char *name) {
|
static int remove_one_link(sd_netlink *rtnl, const char *name) {
|
||||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||||
|
@ -171,48 +169,6 @@ static int add_veth(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is almost base64char(), but not entirely, as it uses the "url and filename safe" alphabet, since we
|
|
||||||
* don't want "/" appear in interface names (since interfaces appear in sysfs as filenames). See section #5
|
|
||||||
* of RFC 4648. */
|
|
||||||
static char urlsafe_base64char(int x) {
|
|
||||||
static const char table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
||||||
"abcdefghijklmnopqrstuvwxyz"
|
|
||||||
"0123456789-_";
|
|
||||||
return table[x & 63];
|
|
||||||
}
|
|
||||||
|
|
||||||
static void shorten_ifname(char *ifname) {
|
|
||||||
char new_ifname[IFNAMSIZ];
|
|
||||||
|
|
||||||
assert(ifname);
|
|
||||||
|
|
||||||
if (strlen(ifname) < IFNAMSIZ) /* Name is short enough */
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (naming_scheme_has(NAMING_NSPAWN_LONG_HASH)) {
|
|
||||||
uint64_t h;
|
|
||||||
|
|
||||||
/* Calculate 64bit hash value */
|
|
||||||
h = siphash24(ifname, strlen(ifname), SHORTEN_IFNAME_HASH_KEY.bytes);
|
|
||||||
|
|
||||||
/* Set the final four bytes (i.e. 32bit) to the lower 24bit of the hash, encoded in url-safe base64 */
|
|
||||||
memcpy(new_ifname, ifname, IFNAMSIZ - 5);
|
|
||||||
new_ifname[IFNAMSIZ - 5] = urlsafe_base64char(h >> 18);
|
|
||||||
new_ifname[IFNAMSIZ - 4] = urlsafe_base64char(h >> 12);
|
|
||||||
new_ifname[IFNAMSIZ - 3] = urlsafe_base64char(h >> 6);
|
|
||||||
new_ifname[IFNAMSIZ - 2] = urlsafe_base64char(h);
|
|
||||||
} else
|
|
||||||
/* On old nspawn versions we just truncated the name, provide compatibility */
|
|
||||||
memcpy(new_ifname, ifname, IFNAMSIZ-1);
|
|
||||||
|
|
||||||
new_ifname[IFNAMSIZ - 1] = 0;
|
|
||||||
|
|
||||||
/* Log the incident to make it more discoverable */
|
|
||||||
log_warning("Network interface name '%s' has been changed to '%s' to fit length constraints.", ifname, new_ifname);
|
|
||||||
|
|
||||||
strcpy(ifname, new_ifname);
|
|
||||||
}
|
|
||||||
|
|
||||||
int setup_veth(const char *machine_name,
|
int setup_veth(const char *machine_name,
|
||||||
pid_t pid,
|
pid_t pid,
|
||||||
char iface_name[IFNAMSIZ],
|
char iface_name[IFNAMSIZ],
|
||||||
|
@ -220,9 +176,7 @@ int setup_veth(const char *machine_name,
|
||||||
|
|
||||||
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
|
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
|
||||||
struct ether_addr mac_host, mac_container;
|
struct ether_addr mac_host, mac_container;
|
||||||
unsigned u;
|
int r, i;
|
||||||
char *n;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(machine_name);
|
assert(machine_name);
|
||||||
assert(pid > 0);
|
assert(pid > 0);
|
||||||
|
@ -230,8 +184,8 @@ int setup_veth(const char *machine_name,
|
||||||
|
|
||||||
/* Use two different interface name prefixes depending whether
|
/* Use two different interface name prefixes depending whether
|
||||||
* we are in bridge mode or not. */
|
* we are in bridge mode or not. */
|
||||||
n = strjoina(bridge ? "vb-" : "ve-", machine_name);
|
snprintf(iface_name, IFNAMSIZ - 1, "%s-%s",
|
||||||
shorten_ifname(n);
|
bridge ? "vb" : "ve", machine_name);
|
||||||
|
|
||||||
r = generate_mac(machine_name, &mac_container, CONTAINER_HASH_KEY, 0);
|
r = generate_mac(machine_name, &mac_container, CONTAINER_HASH_KEY, 0);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
@ -245,16 +199,15 @@ int setup_veth(const char *machine_name,
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to connect to netlink: %m");
|
return log_error_errno(r, "Failed to connect to netlink: %m");
|
||||||
|
|
||||||
r = add_veth(rtnl, pid, n, &mac_host, "host0", &mac_container);
|
r = add_veth(rtnl, pid, iface_name, &mac_host, "host0", &mac_container);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
u = if_nametoindex(n);
|
r = parse_ifindex_or_ifname(iface_name, &i);
|
||||||
if (u == 0)
|
if (r < 0)
|
||||||
return log_error_errno(errno, "Failed to resolve interface %s: %m", n);
|
return log_error_errno(r, "Failed to resolve interface %s: %m", iface_name);
|
||||||
|
|
||||||
strcpy(iface_name, n);
|
return i;
|
||||||
return (int) u;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int setup_veth_extra(
|
int setup_veth_extra(
|
||||||
|
@ -442,50 +395,40 @@ int remove_bridge(const char *bridge_name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_interface(const char *name) {
|
static int parse_interface(const char *name) {
|
||||||
|
_cleanup_(sd_device_unrefp) sd_device *d = NULL;
|
||||||
int ifi, r;
|
int ifi, r;
|
||||||
|
|
||||||
r = parse_ifindex_or_ifname(name, &ifi);
|
r = parse_ifindex_or_ifname(name, &ifi);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to resolve interface %s: %m", name);
|
return log_error_errno(r, "Failed to resolve interface %s: %m", name);
|
||||||
|
|
||||||
|
if (path_is_read_only_fs("/sys") <= 0) {
|
||||||
|
char ifi_str[2 + DECIMAL_STR_MAX(int)];
|
||||||
|
|
||||||
|
/* udev should be around. */
|
||||||
|
|
||||||
|
sprintf(ifi_str, "n%i", ifi);
|
||||||
|
r = sd_device_new_from_device_id(&d, ifi_str);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to get device %s: %m", name);
|
||||||
|
|
||||||
|
r = sd_device_get_is_initialized(d);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to determine whether interface %s is initialized: %m", name);
|
||||||
|
if (r == 0)
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(EBUSY), "Network interface %s is not initialized yet.", name);
|
||||||
|
|
||||||
|
r = device_is_renaming(d);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to determine the interface %s is being renamed: %m", name);
|
||||||
|
if (r > 0)
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(EBUSY), "Interface %s is being renamed.", name);
|
||||||
|
}
|
||||||
|
|
||||||
return ifi;
|
return ifi;
|
||||||
}
|
}
|
||||||
|
|
||||||
int test_network_interface_initialized(const char *name) {
|
int move_network_interfaces(pid_t pid, char **ifaces) {
|
||||||
_cleanup_(sd_device_unrefp) sd_device *d = NULL;
|
|
||||||
int ifi, r;
|
|
||||||
char ifi_str[2 + DECIMAL_STR_MAX(int)];
|
|
||||||
|
|
||||||
if (path_is_read_only_fs("/sys"))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* udev should be around. */
|
|
||||||
|
|
||||||
ifi = parse_interface(name);
|
|
||||||
if (ifi < 0)
|
|
||||||
return ifi;
|
|
||||||
|
|
||||||
sprintf(ifi_str, "n%i", ifi);
|
|
||||||
r = sd_device_new_from_device_id(&d, ifi_str);
|
|
||||||
if (r < 0)
|
|
||||||
return log_error_errno(r, "Failed to get device %s: %m", name);
|
|
||||||
|
|
||||||
r = sd_device_get_is_initialized(d);
|
|
||||||
if (r < 0)
|
|
||||||
return log_error_errno(r, "Failed to determine whether interface %s is initialized: %m", name);
|
|
||||||
if (r == 0)
|
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EBUSY), "Network interface %s is not initialized yet.", name);
|
|
||||||
|
|
||||||
r = device_is_renaming(d);
|
|
||||||
if (r < 0)
|
|
||||||
return log_error_errno(r, "Failed to determine the interface %s is being renamed: %m", name);
|
|
||||||
if (r > 0)
|
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EBUSY), "Interface %s is being renamed.", name);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int move_network_interfaces(int netns_fd, char **ifaces) {
|
|
||||||
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
|
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
|
||||||
char **i;
|
char **i;
|
||||||
int r;
|
int r;
|
||||||
|
@ -509,9 +452,9 @@ int move_network_interfaces(int netns_fd, char **ifaces) {
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to allocate netlink message: %m");
|
return log_error_errno(r, "Failed to allocate netlink message: %m");
|
||||||
|
|
||||||
r = sd_netlink_message_append_u32(m, IFLA_NET_NS_FD, netns_fd);
|
r = sd_netlink_message_append_u32(m, IFLA_NET_NS_PID, pid);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to append namespace fd to netlink message: %m");
|
return log_error_errno(r, "Failed to append namespace PID to netlink message: %m");
|
||||||
|
|
||||||
r = sd_netlink_call(rtnl, m, 0, NULL);
|
r = sd_netlink_call(rtnl, m, 0, NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
@ -560,7 +503,7 @@ int setup_macvlan(const char *machine_name, pid_t pid, char **ifaces) {
|
||||||
if (!n)
|
if (!n)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
shorten_ifname(n);
|
strshorten(n, IFNAMSIZ-1);
|
||||||
|
|
||||||
r = sd_netlink_message_append_string(m, IFLA_IFNAME, n);
|
r = sd_netlink_message_append_string(m, IFLA_IFNAME, n);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
@ -635,7 +578,7 @@ int setup_ipvlan(const char *machine_name, pid_t pid, char **ifaces) {
|
||||||
if (!n)
|
if (!n)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
shorten_ifname(n);
|
strshorten(n, IFNAMSIZ-1);
|
||||||
|
|
||||||
r = sd_netlink_message_append_string(m, IFLA_IFNAME, n);
|
r = sd_netlink_message_append_string(m, IFLA_IFNAME, n);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
|
|
@ -5,8 +5,6 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
int test_network_interface_initialized(const char *name);
|
|
||||||
|
|
||||||
int setup_veth(const char *machine_name, pid_t pid, char iface_name[IFNAMSIZ], bool bridge);
|
int setup_veth(const char *machine_name, pid_t pid, char iface_name[IFNAMSIZ], bool bridge);
|
||||||
int setup_veth_extra(const char *machine_name, pid_t pid, char **pairs);
|
int setup_veth_extra(const char *machine_name, pid_t pid, char **pairs);
|
||||||
|
|
||||||
|
@ -16,7 +14,7 @@ int remove_bridge(const char *bridge_name);
|
||||||
int setup_macvlan(const char *machine_name, pid_t pid, char **ifaces);
|
int setup_macvlan(const char *machine_name, pid_t pid, char **ifaces);
|
||||||
int setup_ipvlan(const char *machine_name, pid_t pid, char **ifaces);
|
int setup_ipvlan(const char *machine_name, pid_t pid, char **ifaces);
|
||||||
|
|
||||||
int move_network_interfaces(int netns_fd, char **ifaces);
|
int move_network_interfaces(pid_t pid, char **ifaces);
|
||||||
|
|
||||||
int veth_extra_parse(char ***l, const char *p);
|
int veth_extra_parse(char ***l, const char *p);
|
||||||
|
|
||||||
|
|
|
@ -848,10 +848,6 @@ static int parse_argv(int argc, char *argv[]) {
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
"Network interface name not valid: %s", optarg);
|
"Network interface name not valid: %s", optarg);
|
||||||
|
|
||||||
r = test_network_interface_initialized(optarg);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (strv_extend(&arg_network_interfaces, optarg) < 0)
|
if (strv_extend(&arg_network_interfaces, optarg) < 0)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
|
@ -865,10 +861,6 @@ static int parse_argv(int argc, char *argv[]) {
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
"MACVLAN network interface name not valid: %s", optarg);
|
"MACVLAN network interface name not valid: %s", optarg);
|
||||||
|
|
||||||
r = test_network_interface_initialized(optarg);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (strv_extend(&arg_network_macvlan, optarg) < 0)
|
if (strv_extend(&arg_network_macvlan, optarg) < 0)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
|
@ -882,10 +874,6 @@ static int parse_argv(int argc, char *argv[]) {
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
"IPVLAN network interface name not valid: %s", optarg);
|
"IPVLAN network interface name not valid: %s", optarg);
|
||||||
|
|
||||||
r = test_network_interface_initialized(optarg);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (strv_extend(&arg_network_ipvlan, optarg) < 0)
|
if (strv_extend(&arg_network_ipvlan, optarg) < 0)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
|
@ -4211,7 +4199,7 @@ static int run_container(
|
||||||
int ifi = 0, r;
|
int ifi = 0, r;
|
||||||
ssize_t l;
|
ssize_t l;
|
||||||
sigset_t mask_chld;
|
sigset_t mask_chld;
|
||||||
_cleanup_close_ int child_netns_fd = -1;
|
_cleanup_close_ int netns_fd = -1;
|
||||||
|
|
||||||
assert_se(sigemptyset(&mask_chld) == 0);
|
assert_se(sigemptyset(&mask_chld) == 0);
|
||||||
assert_se(sigaddset(&mask_chld, SIGCHLD) == 0);
|
assert_se(sigaddset(&mask_chld, SIGCHLD) == 0);
|
||||||
|
@ -4270,11 +4258,11 @@ static int run_container(
|
||||||
return log_error_errno(errno, "Failed to install SIGCHLD handler: %m");
|
return log_error_errno(errno, "Failed to install SIGCHLD handler: %m");
|
||||||
|
|
||||||
if (arg_network_namespace_path) {
|
if (arg_network_namespace_path) {
|
||||||
child_netns_fd = open(arg_network_namespace_path, O_RDONLY|O_NOCTTY|O_CLOEXEC);
|
netns_fd = open(arg_network_namespace_path, O_RDONLY|O_NOCTTY|O_CLOEXEC);
|
||||||
if (child_netns_fd < 0)
|
if (netns_fd < 0)
|
||||||
return log_error_errno(errno, "Cannot open file %s: %m", arg_network_namespace_path);
|
return log_error_errno(errno, "Cannot open file %s: %m", arg_network_namespace_path);
|
||||||
|
|
||||||
r = fd_is_network_ns(child_netns_fd);
|
r = fd_is_network_ns(netns_fd);
|
||||||
if (r == -EUCLEAN)
|
if (r == -EUCLEAN)
|
||||||
log_debug_errno(r, "Cannot determine if passed network namespace path '%s' really refers to a network namespace, assuming it does.", arg_network_namespace_path);
|
log_debug_errno(r, "Cannot determine if passed network namespace path '%s' really refers to a network namespace, assuming it does.", arg_network_namespace_path);
|
||||||
else if (r < 0)
|
else if (r < 0)
|
||||||
|
@ -4319,7 +4307,7 @@ static int run_container(
|
||||||
master_pty_socket_pair[1],
|
master_pty_socket_pair[1],
|
||||||
unified_cgroup_hierarchy_socket_pair[1],
|
unified_cgroup_hierarchy_socket_pair[1],
|
||||||
fds,
|
fds,
|
||||||
child_netns_fd);
|
netns_fd);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
|
|
||||||
|
@ -4421,15 +4409,7 @@ static int run_container(
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(ESRCH), "Child died too early");
|
return log_error_errno(SYNTHETIC_ERRNO(ESRCH), "Child died too early");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (child_netns_fd < 0) {
|
r = move_network_interfaces(*pid, arg_network_interfaces);
|
||||||
/* Make sure we have an open file descriptor to the child's network
|
|
||||||
* namespace so it stays alive even if the child exits. */
|
|
||||||
r = namespace_open(*pid, NULL, NULL, &child_netns_fd, NULL, NULL);
|
|
||||||
if (r < 0)
|
|
||||||
return log_error_errno(r, "Failed to open child network namespace: %m");
|
|
||||||
}
|
|
||||||
|
|
||||||
r = move_network_interfaces(child_netns_fd, arg_network_interfaces);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -4675,36 +4655,6 @@ static int run_container(
|
||||||
/* Normally redundant, but better safe than sorry */
|
/* Normally redundant, but better safe than sorry */
|
||||||
(void) kill(*pid, SIGKILL);
|
(void) kill(*pid, SIGKILL);
|
||||||
|
|
||||||
if (arg_private_network) {
|
|
||||||
/* Move network interfaces back to the parent network namespace. We use `safe_fork`
|
|
||||||
* to avoid having to move the parent to the child network namespace. */
|
|
||||||
r = safe_fork(NULL, FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_WAIT|FORK_LOG, NULL);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (r == 0) {
|
|
||||||
_cleanup_close_ int parent_netns_fd = -1;
|
|
||||||
|
|
||||||
r = namespace_open(getpid(), NULL, NULL, &parent_netns_fd, NULL, NULL);
|
|
||||||
if (r < 0) {
|
|
||||||
log_error_errno(r, "Failed to open parent network namespace: %m");
|
|
||||||
_exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
r = namespace_enter(-1, -1, child_netns_fd, -1, -1);
|
|
||||||
if (r < 0) {
|
|
||||||
log_error_errno(r, "Failed to enter child network namespace: %m");
|
|
||||||
_exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
r = move_network_interfaces(parent_netns_fd, arg_network_interfaces);
|
|
||||||
if (r < 0)
|
|
||||||
log_error_errno(r, "Failed to move network interfaces back to parent network namespace: %m");
|
|
||||||
|
|
||||||
_exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r = wait_for_container(*pid, &container_status);
|
r = wait_for_container(*pid, &container_status);
|
||||||
*pid = 0;
|
*pid = 0;
|
||||||
|
|
||||||
|
|
|
@ -130,8 +130,6 @@ shared_sources = files('''
|
||||||
module-util.h
|
module-util.h
|
||||||
mount-util.c
|
mount-util.c
|
||||||
mount-util.h
|
mount-util.h
|
||||||
netif-naming-scheme.c
|
|
||||||
netif-naming-scheme.h
|
|
||||||
nscd-flush.c
|
nscd-flush.c
|
||||||
nscd-flush.h
|
nscd-flush.h
|
||||||
nsflags.c
|
nsflags.c
|
||||||
|
|
|
@ -40,6 +40,8 @@ libudev_core_sources = '''
|
||||||
udev-builtin-usb_id.c
|
udev-builtin-usb_id.c
|
||||||
net/link-config.c
|
net/link-config.c
|
||||||
net/link-config.h
|
net/link-config.h
|
||||||
|
net/naming-scheme.c
|
||||||
|
net/naming-scheme.h
|
||||||
'''.split()
|
'''.split()
|
||||||
|
|
||||||
if conf.get('HAVE_KMOD') == 1
|
if conf.get('HAVE_KMOD') == 1
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
#include "link-config.h"
|
#include "link-config.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "memory-util.h"
|
#include "memory-util.h"
|
||||||
#include "netif-naming-scheme.h"
|
#include "naming-scheme.h"
|
||||||
#include "netlink-util.h"
|
#include "netlink-util.h"
|
||||||
#include "network-internal.h"
|
#include "network-internal.h"
|
||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||||
|
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
#include "netif-naming-scheme.h"
|
#include "naming-scheme.h"
|
||||||
#include "proc-cmdline.h"
|
#include "proc-cmdline.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
|
|
||||||
|
@ -11,7 +10,6 @@ static const NamingScheme naming_schemes[] = {
|
||||||
{ "v240", NAMING_V240 },
|
{ "v240", NAMING_V240 },
|
||||||
{ "v241", NAMING_V241 },
|
{ "v241", NAMING_V241 },
|
||||||
{ "v243", NAMING_V243 },
|
{ "v243", NAMING_V243 },
|
||||||
{ "v245", NAMING_V245 },
|
|
||||||
/* … add more schemes here, as the logic to name devices is updated … */
|
/* … add more schemes here, as the logic to name devices is updated … */
|
||||||
};
|
};
|
||||||
|
|
|
@ -30,7 +30,6 @@ typedef enum NamingSchemeFlags {
|
||||||
NAMING_STABLE_VIRTUAL_MACS = 1 << 5, /* Use device name to generate MAC, see 6d3646406560 */
|
NAMING_STABLE_VIRTUAL_MACS = 1 << 5, /* Use device name to generate MAC, see 6d3646406560 */
|
||||||
NAMING_NETDEVSIM = 1 << 6, /* Generate names for netdevsim devices, see eaa9d507d855 */
|
NAMING_NETDEVSIM = 1 << 6, /* Generate names for netdevsim devices, see eaa9d507d855 */
|
||||||
NAMING_LABEL_NOPREFIX = 1 << 7, /* Don't prepend ID_NET_LABEL_ONBOARD with interface type prefix */
|
NAMING_LABEL_NOPREFIX = 1 << 7, /* Don't prepend ID_NET_LABEL_ONBOARD with interface type prefix */
|
||||||
NAMING_NSPAWN_LONG_HASH = 1 << 8, /* Shorten nspawn interfaces by including 24bit hash, instead of simple truncation */
|
|
||||||
|
|
||||||
/* And now the masks that combine the features above */
|
/* And now the masks that combine the features above */
|
||||||
NAMING_V238 = 0,
|
NAMING_V238 = 0,
|
||||||
|
@ -38,7 +37,6 @@ typedef enum NamingSchemeFlags {
|
||||||
NAMING_V240 = NAMING_V239 | NAMING_INFINIBAND | NAMING_ZERO_ACPI_INDEX | NAMING_ALLOW_RERENAMES,
|
NAMING_V240 = NAMING_V239 | NAMING_INFINIBAND | NAMING_ZERO_ACPI_INDEX | NAMING_ALLOW_RERENAMES,
|
||||||
NAMING_V241 = NAMING_V240 | NAMING_STABLE_VIRTUAL_MACS,
|
NAMING_V241 = NAMING_V240 | NAMING_STABLE_VIRTUAL_MACS,
|
||||||
NAMING_V243 = NAMING_V241 | NAMING_NETDEVSIM | NAMING_LABEL_NOPREFIX,
|
NAMING_V243 = NAMING_V241 | NAMING_NETDEVSIM | NAMING_LABEL_NOPREFIX,
|
||||||
NAMING_V245 = NAMING_V243 | NAMING_NSPAWN_LONG_HASH,
|
|
||||||
|
|
||||||
_NAMING_SCHEME_FLAGS_INVALID = -1,
|
_NAMING_SCHEME_FLAGS_INVALID = -1,
|
||||||
} NamingSchemeFlags;
|
} NamingSchemeFlags;
|
|
@ -27,7 +27,7 @@
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
#include "fs-util.h"
|
#include "fs-util.h"
|
||||||
#include "netif-naming-scheme.h"
|
#include "naming-scheme.h"
|
||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
#include "proc-cmdline.h"
|
#include "proc-cmdline.h"
|
||||||
#include "stdio-util.h"
|
#include "stdio-util.h"
|
||||||
|
|
|
@ -125,7 +125,6 @@ FastOpenNoCookie=
|
||||||
Source=
|
Source=
|
||||||
Metric=
|
Metric=
|
||||||
TTLPropagate=
|
TTLPropagate=
|
||||||
MultiPathRoute=
|
|
||||||
[Network]
|
[Network]
|
||||||
IPv6DuplicateAddressDetection=
|
IPv6DuplicateAddressDetection=
|
||||||
IPMasquerade=
|
IPMasquerade=
|
||||||
|
|
|
@ -12,10 +12,6 @@ IPv4LLRoute=yes
|
||||||
Destination=2001:1234:5:8fff:ff:ff:ff:ff/128
|
Destination=2001:1234:5:8fff:ff:ff:ff:ff/128
|
||||||
Scope=link
|
Scope=link
|
||||||
|
|
||||||
[Route]
|
|
||||||
Destination=2001:1234:5:9fff:ff:ff:ff:ff/128
|
|
||||||
Scope=link
|
|
||||||
|
|
||||||
[Route]
|
[Route]
|
||||||
Destination=::/0
|
Destination=::/0
|
||||||
Gateway=2001:1234:5:8fff:ff:ff:ff:ff
|
Gateway=2001:1234:5:8fff:ff:ff:ff:ff
|
||||||
|
@ -66,18 +62,3 @@ Destination=149.10.123.3
|
||||||
[Route]
|
[Route]
|
||||||
Type=multicast
|
Type=multicast
|
||||||
Destination=149.10.123.4
|
Destination=149.10.123.4
|
||||||
|
|
||||||
[Route]
|
|
||||||
Destination=192.168.10.1/32
|
|
||||||
MultiPathRoute=149.10.124.59@dummy98 10
|
|
||||||
MultiPathRoute=149.10.124.60@dummy98 5
|
|
||||||
|
|
||||||
[Route]
|
|
||||||
Destination=2001:1234:5:7fff:ff:ff:ff:ff/128
|
|
||||||
MultiPathRoute=2001:1234:5:8fff:ff:ff:ff:ff@dummy98 10
|
|
||||||
MultiPathRoute=2001:1234:5:9fff:ff:ff:ff:ff@dummy98 5
|
|
||||||
|
|
||||||
[Route]
|
|
||||||
Destination=192.168.10.2/32
|
|
||||||
MultiPathRoute=2001:1234:5:8fff:ff:ff:ff:ff@dummy98 10
|
|
||||||
MultiPathRoute=2001:1234:5:9fff:ff:ff:ff:ff@dummy98 5
|
|
||||||
|
|
|
@ -1812,30 +1812,6 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
|
||||||
print(output)
|
print(output)
|
||||||
self.assertRegex(output, 'prohibit 202.54.1.4 proto static')
|
self.assertRegex(output, 'prohibit 202.54.1.4 proto static')
|
||||||
|
|
||||||
print('### ip route show 192.168.10.1')
|
|
||||||
output = check_output('ip route show 192.168.10.1')
|
|
||||||
print(output)
|
|
||||||
self.assertRegex(output, '192.168.10.1 proto static')
|
|
||||||
self.assertRegex(output, 'nexthop via 149.10.124.59 dev dummy98 weight 10')
|
|
||||||
self.assertRegex(output, 'nexthop via 149.10.124.60 dev dummy98 weight 5')
|
|
||||||
|
|
||||||
print('### ip route show 192.168.10.2')
|
|
||||||
output = check_output('ip route show 192.168.10.2')
|
|
||||||
print(output)
|
|
||||||
# old ip command does not show IPv6 gateways...
|
|
||||||
self.assertRegex(output, '192.168.10.2 proto static')
|
|
||||||
self.assertRegex(output, 'nexthop')
|
|
||||||
self.assertRegex(output, 'dev dummy98 weight 10')
|
|
||||||
self.assertRegex(output, 'dev dummy98 weight 5')
|
|
||||||
|
|
||||||
print('### ip -6 route show 2001:1234:5:7fff:ff:ff:ff:ff')
|
|
||||||
output = check_output('ip -6 route show 2001:1234:5:7fff:ff:ff:ff:ff')
|
|
||||||
print(output)
|
|
||||||
# old ip command does not show 'nexthop' keyword and weight...
|
|
||||||
self.assertRegex(output, '2001:1234:5:7fff:ff:ff:ff:ff')
|
|
||||||
self.assertRegex(output, 'via 2001:1234:5:8fff:ff:ff:ff:ff dev dummy98')
|
|
||||||
self.assertRegex(output, 'via 2001:1234:5:9fff:ff:ff:ff:ff dev dummy98')
|
|
||||||
|
|
||||||
def test_gateway_reconfigure(self):
|
def test_gateway_reconfigure(self):
|
||||||
copy_unit_to_networkd_unit_path('25-gateway-static.network', '12-dummy.netdev')
|
copy_unit_to_networkd_unit_path('25-gateway-static.network', '12-dummy.netdev')
|
||||||
start_networkd()
|
start_networkd()
|
||||||
|
|
Loading…
Reference in New Issue