mirror of
https://github.com/systemd/systemd
synced 2026-04-13 18:44:51 +02:00
Compare commits
15 Commits
b09869eaf7
...
acac88340a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
acac88340a | ||
|
|
de843f8582 | ||
|
|
1bc8417cfe | ||
|
|
1e8e9730d2 | ||
|
|
a03ff4c0fe | ||
|
|
0eed039c92 | ||
|
|
df25b9e48c | ||
|
|
252e96eaa9 | ||
|
|
41ce9d769d | ||
|
|
bd29dfef8b | ||
|
|
b4fd34d81c | ||
|
|
307fe3cdf2 | ||
|
|
e5c4289a9d | ||
|
|
e217e22a77 | ||
|
|
cfd1d61fe4 |
@ -946,6 +946,104 @@
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>SR-IOVVirtualFunctions=</varname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>Specifies the number of SR-IOV virtual functions. Takes an integer in the range
|
||||||
|
0…2147483647. Defaults to unset, and automatically determined from the values specified in
|
||||||
|
the <varname>VirtualFunction=</varname> settings in the [SR-IOV] sections.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1 id='sr-iov'>
|
||||||
|
<title>[SR-IOV] Section Options</title>
|
||||||
|
<para>The [SR-IOV] section accepts the following keys. Specify several [SR-IOV] sections to
|
||||||
|
configure several SR-IOVs. SR-IOV provides the ability to partition a single physical PCI resource
|
||||||
|
into virtual PCI functions which can then be injected into a VM. In the case of network VFs, SR-IOV
|
||||||
|
improves north-south network performance (that is, traffic with endpoints outside the host machine)
|
||||||
|
by allowing traffic to bypass the host machine’s network stack.</para>
|
||||||
|
|
||||||
|
<variablelist class='network-directives'>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>VirtualFunction=</varname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>Specifies a Virtual Function (VF), lightweight PCIe function designed solely to move
|
||||||
|
data in and out. Takes an integer in the range 0…2147483646. This option is compulsory.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>VLANId=</varname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>Specifies VLAN ID of the virtual function. Takes an integer in the range 1…4095.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>QualityOfService=</varname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>Specifies quality of service of the virtual function. Takes an integer in the range
|
||||||
|
1…4294967294.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>VLANProtocol=</varname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>Specifies VLAN protocol of the virtual function. Takes <literal>802.1Q</literal> or
|
||||||
|
<literal>802.1ad</literal>.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>MACSpoofCheck=</varname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>Takes a boolean. Controls the MAC spoof checking. When unset, the kernel's default will
|
||||||
|
be used.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>QueryReceiveSideScaling=</varname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>Takes a boolean. Toggle the ability of querying the receive side scaling (RSS)
|
||||||
|
configuration of the virtual function (VF). The VF RSS information like RSS hash key may be
|
||||||
|
considered sensitive on some devices where this information is shared between VF and the
|
||||||
|
physical function (PF). When unset, the kernel's default will be used.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>Trust=</varname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>Takes a boolean. Allows one to set trust mode of the virtual function (VF). When set,
|
||||||
|
VF users can set a specific feature which may impact security and/or performance. When unset,
|
||||||
|
the kernel's default will be used.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>LinkState=</varname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>Allows one to set the link state of the virtual function (VF). Takes a boolean or a
|
||||||
|
special value <literal>auto</literal>. Setting to <literal>auto</literal> means a
|
||||||
|
reflection of the physical function (PF) link state, <literal>yes</literal> lets the VF to
|
||||||
|
communicate with other VFs on this host even if the PF link state is down,
|
||||||
|
<literal>no</literal> causes the hardware to drop any packets sent by the VF. When unset,
|
||||||
|
the kernel's default will be used.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>MACAddress=</varname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>Specifies the MAC address for the virtual function.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
|||||||
@ -300,94 +300,7 @@
|
|||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<xi:include href="systemd.link.xml" xpointer="sr-iov" />
|
||||||
<title>[SR-IOV] Section Options</title>
|
|
||||||
<para>The [SR-IOV] section accepts the following keys. Specify several [SR-IOV] sections to
|
|
||||||
configure several SR-IOVs. SR-IOV provides the ability to partition a single physical PCI resource
|
|
||||||
into virtual PCI functions which can then be injected into a VM. In the case of network VFs, SR-IOV
|
|
||||||
improves north-south network performance (that is, traffic with endpoints outside the host machine)
|
|
||||||
by allowing traffic to bypass the host machine’s network stack.</para>
|
|
||||||
|
|
||||||
<variablelist class='network-directives'>
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>VirtualFunction=</varname></term>
|
|
||||||
<listitem>
|
|
||||||
<para>Specifies a Virtual Function (VF), lightweight PCIe function designed solely to move
|
|
||||||
data in and out. Takes an integer in the range 0…2147483646. This option is compulsory.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>VLANId=</varname></term>
|
|
||||||
<listitem>
|
|
||||||
<para>Specifies VLAN ID of the virtual function. Takes an integer in the range 1…4095.</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>QualityOfService=</varname></term>
|
|
||||||
<listitem>
|
|
||||||
<para>Specifies quality of service of the virtual function. Takes an integer in the range
|
|
||||||
1…4294967294.</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>VLANProtocol=</varname></term>
|
|
||||||
<listitem>
|
|
||||||
<para>Specifies VLAN protocol of the virtual function. Takes <literal>802.1Q</literal> or
|
|
||||||
<literal>802.1ad</literal>.</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>MACSpoofCheck=</varname></term>
|
|
||||||
<listitem>
|
|
||||||
<para>Takes a boolean. Controls the MAC spoof checking. When unset, the kernel's default will
|
|
||||||
be used.</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>QueryReceiveSideScaling=</varname></term>
|
|
||||||
<listitem>
|
|
||||||
<para>Takes a boolean. Toggle the ability of querying the receive side scaling (RSS)
|
|
||||||
configuration of the virtual function (VF). The VF RSS information like RSS hash key may be
|
|
||||||
considered sensitive on some devices where this information is shared between VF and the
|
|
||||||
physical function (PF). When unset, the kernel's default will be used.</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>Trust=</varname></term>
|
|
||||||
<listitem>
|
|
||||||
<para>Takes a boolean. Allows one to set trust mode of the virtual function (VF). When set, VF
|
|
||||||
users can set a specific feature which may impact security and/or performance. When unset,
|
|
||||||
the kernel's default will be used.</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>LinkState=</varname></term>
|
|
||||||
<listitem>
|
|
||||||
<para>Allows one to set the link state of the virtual function (VF). Takes a boolean or a
|
|
||||||
special value <literal>auto</literal>. Setting to <literal>auto</literal> means a
|
|
||||||
reflection of the physical function (PF) link state, <literal>yes</literal> lets the VF to
|
|
||||||
communicate with other VFs on this host even if the PF link state is down,
|
|
||||||
<literal>no</literal> causes the hardware to drop any packets sent by the VF. When unset,
|
|
||||||
the kernel's default will be used.</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>MACAddress=</varname></term>
|
|
||||||
<listitem>
|
|
||||||
<para>Specifies the MAC address for the virtual function.</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
<title>[Network] Section Options</title>
|
<title>[Network] Section Options</title>
|
||||||
|
|||||||
@ -210,7 +210,17 @@ if get_option('b_lto')
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
foreach arg : get_option('c_args')
|
foreach arg : get_option('c_args')
|
||||||
if arg in ['-Werror', '-g', '-ggdb', '-O1', '-O2', '-O3', '-Og', '-Os', '-DNDEBUG', '-flto', '-fno-lto']
|
if arg in [
|
||||||
|
'-DNDEBUG',
|
||||||
|
'-fno-lto',
|
||||||
|
'-g', '-ggdb',
|
||||||
|
'-O1', '-O2', '-O3', '-Og', '-Os',
|
||||||
|
'-Werror',
|
||||||
|
] or arg.split('=')[0] in [
|
||||||
|
'-ffile-prefix-map',
|
||||||
|
'-flto',
|
||||||
|
]
|
||||||
|
|
||||||
message('Using "@0@" from c_args for EFI compiler'.format(arg))
|
message('Using "@0@" from c_args for EFI compiler'.format(arg))
|
||||||
efi_cflags += arg
|
efi_cflags += arg
|
||||||
endif
|
endif
|
||||||
|
|||||||
@ -110,7 +110,7 @@ static int set_interface_name(struct introspect *intro, const char *interface_na
|
|||||||
return free_and_strdup(&intro->interface_name, interface_name);
|
return free_and_strdup(&intro->interface_name, interface_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
int introspect_write_child_nodes(struct introspect *i, Set *s, const char *prefix) {
|
int introspect_write_child_nodes(struct introspect *i, OrderedSet *s, const char *prefix) {
|
||||||
char *node;
|
char *node;
|
||||||
|
|
||||||
assert(i);
|
assert(i);
|
||||||
@ -118,7 +118,7 @@ int introspect_write_child_nodes(struct introspect *i, Set *s, const char *prefi
|
|||||||
|
|
||||||
assert_se(set_interface_name(i, NULL) >= 0);
|
assert_se(set_interface_name(i, NULL) >= 0);
|
||||||
|
|
||||||
while ((node = set_steal_first(s))) {
|
while ((node = ordered_set_steal_first(s))) {
|
||||||
const char *e;
|
const char *e;
|
||||||
|
|
||||||
e = object_path_startswith(node, prefix);
|
e = object_path_startswith(node, prefix);
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
#include "sd-bus.h"
|
#include "sd-bus.h"
|
||||||
|
|
||||||
#include "set.h"
|
#include "ordered-set.h"
|
||||||
|
|
||||||
struct introspect {
|
struct introspect {
|
||||||
FILE *f;
|
FILE *f;
|
||||||
@ -17,7 +17,7 @@ struct introspect {
|
|||||||
|
|
||||||
int introspect_begin(struct introspect *i, bool trusted);
|
int introspect_begin(struct introspect *i, bool trusted);
|
||||||
int introspect_write_default_interfaces(struct introspect *i, bool object_manager);
|
int introspect_write_default_interfaces(struct introspect *i, bool object_manager);
|
||||||
int introspect_write_child_nodes(struct introspect *i, Set *s, const char *prefix);
|
int introspect_write_child_nodes(struct introspect *i, OrderedSet *s, const char *prefix);
|
||||||
int introspect_write_interface(
|
int introspect_write_interface(
|
||||||
struct introspect *i,
|
struct introspect *i,
|
||||||
const char *interface_name,
|
const char *interface_name,
|
||||||
|
|||||||
@ -9,7 +9,6 @@
|
|||||||
#include "bus-slot.h"
|
#include "bus-slot.h"
|
||||||
#include "bus-type.h"
|
#include "bus-type.h"
|
||||||
#include "missing_capability.h"
|
#include "missing_capability.h"
|
||||||
#include "set.h"
|
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
|
|
||||||
@ -99,7 +98,7 @@ static int add_enumerated_to_set(
|
|||||||
sd_bus *bus,
|
sd_bus *bus,
|
||||||
const char *prefix,
|
const char *prefix,
|
||||||
struct node_enumerator *first,
|
struct node_enumerator *first,
|
||||||
Set *s,
|
OrderedSet *s,
|
||||||
sd_bus_error *error) {
|
sd_bus_error *error) {
|
||||||
|
|
||||||
struct node_enumerator *c;
|
struct node_enumerator *c;
|
||||||
@ -146,7 +145,7 @@ static int add_enumerated_to_set(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = set_consume(s, *k);
|
r = ordered_set_consume(s, *k);
|
||||||
if (r == -EEXIST)
|
if (r == -EEXIST)
|
||||||
r = 0;
|
r = 0;
|
||||||
}
|
}
|
||||||
@ -171,7 +170,7 @@ static int add_subtree_to_set(
|
|||||||
const char *prefix,
|
const char *prefix,
|
||||||
struct node *n,
|
struct node *n,
|
||||||
unsigned flags,
|
unsigned flags,
|
||||||
Set *s,
|
OrderedSet *s,
|
||||||
sd_bus_error *error) {
|
sd_bus_error *error) {
|
||||||
|
|
||||||
struct node *i;
|
struct node *i;
|
||||||
@ -198,7 +197,7 @@ static int add_subtree_to_set(
|
|||||||
if (!t)
|
if (!t)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
r = set_consume(s, t);
|
r = ordered_set_consume(s, t);
|
||||||
if (r < 0 && r != -EEXIST)
|
if (r < 0 && r != -EEXIST)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -220,10 +219,10 @@ static int get_child_nodes(
|
|||||||
const char *prefix,
|
const char *prefix,
|
||||||
struct node *n,
|
struct node *n,
|
||||||
unsigned flags,
|
unsigned flags,
|
||||||
Set **_s,
|
OrderedSet **_s,
|
||||||
sd_bus_error *error) {
|
sd_bus_error *error) {
|
||||||
|
|
||||||
Set *s = NULL;
|
OrderedSet *s = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(bus);
|
assert(bus);
|
||||||
@ -231,13 +230,13 @@ static int get_child_nodes(
|
|||||||
assert(n);
|
assert(n);
|
||||||
assert(_s);
|
assert(_s);
|
||||||
|
|
||||||
s = set_new(&string_hash_ops);
|
s = ordered_set_new(&string_hash_ops);
|
||||||
if (!s)
|
if (!s)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
r = add_subtree_to_set(bus, prefix, n, flags, s, error);
|
r = add_subtree_to_set(bus, prefix, n, flags, s, error);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
set_free_free(s);
|
ordered_set_free_free(s);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -937,7 +936,7 @@ int introspect_path(
|
|||||||
char **ret,
|
char **ret,
|
||||||
sd_bus_error *error) {
|
sd_bus_error *error) {
|
||||||
|
|
||||||
_cleanup_set_free_free_ Set *s = NULL;
|
_cleanup_ordered_set_free_ OrderedSet *s = NULL;
|
||||||
_cleanup_(introspect_free) struct introspect intro = {};
|
_cleanup_(introspect_free) struct introspect intro = {};
|
||||||
struct node_vtable *c;
|
struct node_vtable *c;
|
||||||
bool empty;
|
bool empty;
|
||||||
@ -963,7 +962,7 @@ int introspect_path(
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
empty = set_isempty(s);
|
empty = ordered_set_isempty(s);
|
||||||
|
|
||||||
LIST_FOREACH(vtables, c, n->vtables) {
|
LIST_FOREACH(vtables, c, n->vtables) {
|
||||||
if (require_fallback && !c->is_fallback)
|
if (require_fallback && !c->is_fallback)
|
||||||
@ -1233,7 +1232,7 @@ static int process_get_managed_objects(
|
|||||||
|
|
||||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||||
_cleanup_set_free_free_ Set *s = NULL;
|
_cleanup_ordered_set_free_free_ OrderedSet *s = NULL;
|
||||||
char *path;
|
char *path;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -1263,7 +1262,7 @@ static int process_get_managed_objects(
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
SET_FOREACH(path, s) {
|
ORDERED_SET_FOREACH(path, s) {
|
||||||
r = object_manager_serialize_path_and_fallbacks(bus, reply, path, &error);
|
r = object_manager_serialize_path_and_fallbacks(bus, reply, path, &error);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return bus_maybe_reply_error(m, r, &error);
|
return bus_maybe_reply_error(m, r, &error);
|
||||||
@ -2352,7 +2351,7 @@ _public_ int sd_bus_emit_properties_changed(
|
|||||||
static int object_added_append_all_prefix(
|
static int object_added_append_all_prefix(
|
||||||
sd_bus *bus,
|
sd_bus *bus,
|
||||||
sd_bus_message *m,
|
sd_bus_message *m,
|
||||||
Set *s,
|
OrderedSet *s,
|
||||||
const char *prefix,
|
const char *prefix,
|
||||||
const char *path,
|
const char *path,
|
||||||
bool require_fallback) {
|
bool require_fallback) {
|
||||||
@ -2392,10 +2391,10 @@ static int object_added_append_all_prefix(
|
|||||||
* skip it on any of its parents. The child vtables
|
* skip it on any of its parents. The child vtables
|
||||||
* always fully override any conflicting vtables of
|
* always fully override any conflicting vtables of
|
||||||
* any parent node. */
|
* any parent node. */
|
||||||
if (set_get(s, c->interface))
|
if (ordered_set_get(s, c->interface))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
r = set_put(s, c->interface);
|
r = ordered_set_put(s, c->interface);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -2441,7 +2440,7 @@ static int object_added_append_all_prefix(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int object_added_append_all(sd_bus *bus, sd_bus_message *m, const char *path) {
|
static int object_added_append_all(sd_bus *bus, sd_bus_message *m, const char *path) {
|
||||||
_cleanup_set_free_ Set *s = NULL;
|
_cleanup_ordered_set_free_ OrderedSet *s = NULL;
|
||||||
_cleanup_free_ char *prefix = NULL;
|
_cleanup_free_ char *prefix = NULL;
|
||||||
size_t pl;
|
size_t pl;
|
||||||
int r;
|
int r;
|
||||||
@ -2465,7 +2464,7 @@ static int object_added_append_all(sd_bus *bus, sd_bus_message *m, const char *p
|
|||||||
* a parent that were overwritten by a child.
|
* a parent that were overwritten by a child.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
s = set_new(&string_hash_ops);
|
s = ordered_set_new(&string_hash_ops);
|
||||||
if (!s)
|
if (!s)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -2572,7 +2571,7 @@ _public_ int sd_bus_emit_object_added(sd_bus *bus, const char *path) {
|
|||||||
static int object_removed_append_all_prefix(
|
static int object_removed_append_all_prefix(
|
||||||
sd_bus *bus,
|
sd_bus *bus,
|
||||||
sd_bus_message *m,
|
sd_bus_message *m,
|
||||||
Set *s,
|
OrderedSet *s,
|
||||||
const char *prefix,
|
const char *prefix,
|
||||||
const char *path,
|
const char *path,
|
||||||
bool require_fallback) {
|
bool require_fallback) {
|
||||||
@ -2605,7 +2604,7 @@ static int object_removed_append_all_prefix(
|
|||||||
* skip it on any of its parents. The child vtables
|
* skip it on any of its parents. The child vtables
|
||||||
* always fully override any conflicting vtables of
|
* always fully override any conflicting vtables of
|
||||||
* any parent node. */
|
* any parent node. */
|
||||||
if (set_get(s, c->interface))
|
if (ordered_set_get(s, c->interface))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
r = node_vtable_get_userdata(bus, path, c, &u, &error);
|
r = node_vtable_get_userdata(bus, path, c, &u, &error);
|
||||||
@ -2616,7 +2615,7 @@ static int object_removed_append_all_prefix(
|
|||||||
if (r == 0)
|
if (r == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
r = set_put(s, c->interface);
|
r = ordered_set_put(s, c->interface);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -2631,7 +2630,7 @@ static int object_removed_append_all_prefix(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int object_removed_append_all(sd_bus *bus, sd_bus_message *m, const char *path) {
|
static int object_removed_append_all(sd_bus *bus, sd_bus_message *m, const char *path) {
|
||||||
_cleanup_set_free_ Set *s = NULL;
|
_cleanup_ordered_set_free_ OrderedSet *s = NULL;
|
||||||
_cleanup_free_ char *prefix = NULL;
|
_cleanup_free_ char *prefix = NULL;
|
||||||
size_t pl;
|
size_t pl;
|
||||||
int r;
|
int r;
|
||||||
@ -2642,7 +2641,7 @@ static int object_removed_append_all(sd_bus *bus, sd_bus_message *m, const char
|
|||||||
|
|
||||||
/* see sd_bus_emit_object_added() for details */
|
/* see sd_bus_emit_object_added() for details */
|
||||||
|
|
||||||
s = set_new(&string_hash_ops);
|
s = ordered_set_new(&string_hash_ops);
|
||||||
if (!s)
|
if (!s)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
|||||||
@ -46,15 +46,15 @@ static L2tpSession* l2tp_session_free(L2tpSession *s) {
|
|||||||
if (s->tunnel && s->section)
|
if (s->tunnel && s->section)
|
||||||
ordered_hashmap_remove(s->tunnel->sessions_by_section, s->section);
|
ordered_hashmap_remove(s->tunnel->sessions_by_section, s->section);
|
||||||
|
|
||||||
network_config_section_free(s->section);
|
config_section_free(s->section);
|
||||||
free(s->name);
|
free(s->name);
|
||||||
return mfree(s);
|
return mfree(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_NETWORK_SECTION_FUNCTIONS(L2tpSession, l2tp_session_free);
|
DEFINE_SECTION_CLEANUP_FUNCTIONS(L2tpSession, l2tp_session_free);
|
||||||
|
|
||||||
static int l2tp_session_new_static(L2tpTunnel *t, const char *filename, unsigned section_line, L2tpSession **ret) {
|
static int l2tp_session_new_static(L2tpTunnel *t, const char *filename, unsigned section_line, L2tpSession **ret) {
|
||||||
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
|
_cleanup_(config_section_freep) ConfigSection *n = NULL;
|
||||||
_cleanup_(l2tp_session_freep) L2tpSession *s = NULL;
|
_cleanup_(l2tp_session_freep) L2tpSession *s = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ static int l2tp_session_new_static(L2tpTunnel *t, const char *filename, unsigned
|
|||||||
assert(filename);
|
assert(filename);
|
||||||
assert(section_line > 0);
|
assert(section_line > 0);
|
||||||
|
|
||||||
r = network_config_section_new(filename, section_line, &n);
|
r = config_section_new(filename, section_line, &n);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ static int l2tp_session_new_static(L2tpTunnel *t, const char *filename, unsigned
|
|||||||
.section = TAKE_PTR(n),
|
.section = TAKE_PTR(n),
|
||||||
};
|
};
|
||||||
|
|
||||||
r = ordered_hashmap_ensure_put(&t->sessions_by_section, &network_config_hash_ops, s->section, s);
|
r = ordered_hashmap_ensure_put(&t->sessions_by_section, &config_section_hash_ops, s->section, s);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|||||||
@ -34,7 +34,7 @@ typedef struct L2tpTunnel L2tpTunnel;
|
|||||||
|
|
||||||
typedef struct L2tpSession {
|
typedef struct L2tpSession {
|
||||||
L2tpTunnel *tunnel;
|
L2tpTunnel *tunnel;
|
||||||
NetworkConfigSection *section;
|
ConfigSection *section;
|
||||||
|
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
|
|||||||
@ -43,16 +43,16 @@ static ReceiveAssociation* macsec_receive_association_free(ReceiveAssociation *c
|
|||||||
if (c->macsec && c->section)
|
if (c->macsec && c->section)
|
||||||
ordered_hashmap_remove(c->macsec->receive_associations_by_section, c->section);
|
ordered_hashmap_remove(c->macsec->receive_associations_by_section, c->section);
|
||||||
|
|
||||||
network_config_section_free(c->section);
|
config_section_free(c->section);
|
||||||
security_association_clear(&c->sa);
|
security_association_clear(&c->sa);
|
||||||
|
|
||||||
return mfree(c);
|
return mfree(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_NETWORK_SECTION_FUNCTIONS(ReceiveAssociation, macsec_receive_association_free);
|
DEFINE_SECTION_CLEANUP_FUNCTIONS(ReceiveAssociation, macsec_receive_association_free);
|
||||||
|
|
||||||
static int macsec_receive_association_new_static(MACsec *s, const char *filename, unsigned section_line, ReceiveAssociation **ret) {
|
static int macsec_receive_association_new_static(MACsec *s, const char *filename, unsigned section_line, ReceiveAssociation **ret) {
|
||||||
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
|
_cleanup_(config_section_freep) ConfigSection *n = NULL;
|
||||||
_cleanup_(macsec_receive_association_freep) ReceiveAssociation *c = NULL;
|
_cleanup_(macsec_receive_association_freep) ReceiveAssociation *c = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ static int macsec_receive_association_new_static(MACsec *s, const char *filename
|
|||||||
assert(filename);
|
assert(filename);
|
||||||
assert(section_line > 0);
|
assert(section_line > 0);
|
||||||
|
|
||||||
r = network_config_section_new(filename, section_line, &n);
|
r = config_section_new(filename, section_line, &n);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ static int macsec_receive_association_new_static(MACsec *s, const char *filename
|
|||||||
|
|
||||||
security_association_init(&c->sa);
|
security_association_init(&c->sa);
|
||||||
|
|
||||||
r = ordered_hashmap_ensure_put(&s->receive_associations_by_section, &network_config_hash_ops, c->section, c);
|
r = ordered_hashmap_ensure_put(&s->receive_associations_by_section, &config_section_hash_ops, c->section, c);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -103,12 +103,12 @@ static ReceiveChannel* macsec_receive_channel_free(ReceiveChannel *c) {
|
|||||||
ordered_hashmap_remove(c->macsec->receive_channels_by_section, c->section);
|
ordered_hashmap_remove(c->macsec->receive_channels_by_section, c->section);
|
||||||
}
|
}
|
||||||
|
|
||||||
network_config_section_free(c->section);
|
config_section_free(c->section);
|
||||||
|
|
||||||
return mfree(c);
|
return mfree(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_NETWORK_SECTION_FUNCTIONS(ReceiveChannel, macsec_receive_channel_free);
|
DEFINE_SECTION_CLEANUP_FUNCTIONS(ReceiveChannel, macsec_receive_channel_free);
|
||||||
|
|
||||||
static int macsec_receive_channel_new(MACsec *s, uint64_t sci, ReceiveChannel **ret) {
|
static int macsec_receive_channel_new(MACsec *s, uint64_t sci, ReceiveChannel **ret) {
|
||||||
ReceiveChannel *c;
|
ReceiveChannel *c;
|
||||||
@ -129,7 +129,7 @@ static int macsec_receive_channel_new(MACsec *s, uint64_t sci, ReceiveChannel **
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int macsec_receive_channel_new_static(MACsec *s, const char *filename, unsigned section_line, ReceiveChannel **ret) {
|
static int macsec_receive_channel_new_static(MACsec *s, const char *filename, unsigned section_line, ReceiveChannel **ret) {
|
||||||
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
|
_cleanup_(config_section_freep) ConfigSection *n = NULL;
|
||||||
_cleanup_(macsec_receive_channel_freep) ReceiveChannel *c = NULL;
|
_cleanup_(macsec_receive_channel_freep) ReceiveChannel *c = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -138,7 +138,7 @@ static int macsec_receive_channel_new_static(MACsec *s, const char *filename, un
|
|||||||
assert(filename);
|
assert(filename);
|
||||||
assert(section_line > 0);
|
assert(section_line > 0);
|
||||||
|
|
||||||
r = network_config_section_new(filename, section_line, &n);
|
r = config_section_new(filename, section_line, &n);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -154,7 +154,7 @@ static int macsec_receive_channel_new_static(MACsec *s, const char *filename, un
|
|||||||
|
|
||||||
c->section = TAKE_PTR(n);
|
c->section = TAKE_PTR(n);
|
||||||
|
|
||||||
r = ordered_hashmap_ensure_put(&s->receive_channels_by_section, &network_config_hash_ops, c->section, c);
|
r = ordered_hashmap_ensure_put(&s->receive_channels_by_section, &config_section_hash_ops, c->section, c);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -170,16 +170,16 @@ static TransmitAssociation* macsec_transmit_association_free(TransmitAssociation
|
|||||||
if (a->macsec && a->section)
|
if (a->macsec && a->section)
|
||||||
ordered_hashmap_remove(a->macsec->transmit_associations_by_section, a->section);
|
ordered_hashmap_remove(a->macsec->transmit_associations_by_section, a->section);
|
||||||
|
|
||||||
network_config_section_free(a->section);
|
config_section_free(a->section);
|
||||||
security_association_clear(&a->sa);
|
security_association_clear(&a->sa);
|
||||||
|
|
||||||
return mfree(a);
|
return mfree(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_NETWORK_SECTION_FUNCTIONS(TransmitAssociation, macsec_transmit_association_free);
|
DEFINE_SECTION_CLEANUP_FUNCTIONS(TransmitAssociation, macsec_transmit_association_free);
|
||||||
|
|
||||||
static int macsec_transmit_association_new_static(MACsec *s, const char *filename, unsigned section_line, TransmitAssociation **ret) {
|
static int macsec_transmit_association_new_static(MACsec *s, const char *filename, unsigned section_line, TransmitAssociation **ret) {
|
||||||
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
|
_cleanup_(config_section_freep) ConfigSection *n = NULL;
|
||||||
_cleanup_(macsec_transmit_association_freep) TransmitAssociation *a = NULL;
|
_cleanup_(macsec_transmit_association_freep) TransmitAssociation *a = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -188,7 +188,7 @@ static int macsec_transmit_association_new_static(MACsec *s, const char *filenam
|
|||||||
assert(filename);
|
assert(filename);
|
||||||
assert(section_line > 0);
|
assert(section_line > 0);
|
||||||
|
|
||||||
r = network_config_section_new(filename, section_line, &n);
|
r = config_section_new(filename, section_line, &n);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -209,7 +209,7 @@ static int macsec_transmit_association_new_static(MACsec *s, const char *filenam
|
|||||||
|
|
||||||
security_association_init(&a->sa);
|
security_association_init(&a->sa);
|
||||||
|
|
||||||
r = ordered_hashmap_ensure_put(&s->transmit_associations_by_section, &network_config_hash_ops, a->section, a);
|
r = ordered_hashmap_ensure_put(&s->transmit_associations_by_section, &config_section_hash_ops, a->section, a);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|||||||
@ -39,14 +39,14 @@ typedef struct SecurityAssociation {
|
|||||||
|
|
||||||
typedef struct TransmitAssociation {
|
typedef struct TransmitAssociation {
|
||||||
MACsec *macsec;
|
MACsec *macsec;
|
||||||
NetworkConfigSection *section;
|
ConfigSection *section;
|
||||||
|
|
||||||
SecurityAssociation sa;
|
SecurityAssociation sa;
|
||||||
} TransmitAssociation;
|
} TransmitAssociation;
|
||||||
|
|
||||||
typedef struct ReceiveAssociation {
|
typedef struct ReceiveAssociation {
|
||||||
MACsec *macsec;
|
MACsec *macsec;
|
||||||
NetworkConfigSection *section;
|
ConfigSection *section;
|
||||||
|
|
||||||
MACsecSCI sci;
|
MACsecSCI sci;
|
||||||
SecurityAssociation sa;
|
SecurityAssociation sa;
|
||||||
@ -54,7 +54,7 @@ typedef struct ReceiveAssociation {
|
|||||||
|
|
||||||
typedef struct ReceiveChannel {
|
typedef struct ReceiveChannel {
|
||||||
MACsec *macsec;
|
MACsec *macsec;
|
||||||
NetworkConfigSection *section;
|
ConfigSection *section;
|
||||||
|
|
||||||
MACsecSCI sci;
|
MACsecSCI sci;
|
||||||
ReceiveAssociation *rxsa[MACSEC_MAX_ASSOCIATION_NUMBER];
|
ReceiveAssociation *rxsa[MACSEC_MAX_ASSOCIATION_NUMBER];
|
||||||
|
|||||||
@ -47,7 +47,7 @@ static WireguardPeer* wireguard_peer_free(WireguardPeer *peer) {
|
|||||||
hashmap_remove(peer->wireguard->peers_by_section, peer->section);
|
hashmap_remove(peer->wireguard->peers_by_section, peer->section);
|
||||||
}
|
}
|
||||||
|
|
||||||
network_config_section_free(peer->section);
|
config_section_free(peer->section);
|
||||||
|
|
||||||
while ((mask = peer->ipmasks)) {
|
while ((mask = peer->ipmasks)) {
|
||||||
LIST_REMOVE(ipmasks, peer->ipmasks, mask);
|
LIST_REMOVE(ipmasks, peer->ipmasks, mask);
|
||||||
@ -65,10 +65,10 @@ static WireguardPeer* wireguard_peer_free(WireguardPeer *peer) {
|
|||||||
return mfree(peer);
|
return mfree(peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_NETWORK_SECTION_FUNCTIONS(WireguardPeer, wireguard_peer_free);
|
DEFINE_SECTION_CLEANUP_FUNCTIONS(WireguardPeer, wireguard_peer_free);
|
||||||
|
|
||||||
static int wireguard_peer_new_static(Wireguard *w, const char *filename, unsigned section_line, WireguardPeer **ret) {
|
static int wireguard_peer_new_static(Wireguard *w, const char *filename, unsigned section_line, WireguardPeer **ret) {
|
||||||
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
|
_cleanup_(config_section_freep) ConfigSection *n = NULL;
|
||||||
_cleanup_(wireguard_peer_freep) WireguardPeer *peer = NULL;
|
_cleanup_(wireguard_peer_freep) WireguardPeer *peer = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ static int wireguard_peer_new_static(Wireguard *w, const char *filename, unsigne
|
|||||||
assert(filename);
|
assert(filename);
|
||||||
assert(section_line > 0);
|
assert(section_line > 0);
|
||||||
|
|
||||||
r = network_config_section_new(filename, section_line, &n);
|
r = config_section_new(filename, section_line, &n);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -99,7 +99,7 @@ static int wireguard_peer_new_static(Wireguard *w, const char *filename, unsigne
|
|||||||
|
|
||||||
LIST_PREPEND(peers, w->peers, peer);
|
LIST_PREPEND(peers, w->peers, peer);
|
||||||
|
|
||||||
r = hashmap_ensure_put(&w->peers_by_section, &network_config_hash_ops, peer->section, peer);
|
r = hashmap_ensure_put(&w->peers_by_section, &config_section_hash_ops, peer->section, peer);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|||||||
@ -24,7 +24,7 @@ typedef struct WireguardIPmask {
|
|||||||
|
|
||||||
typedef struct WireguardPeer {
|
typedef struct WireguardPeer {
|
||||||
Wireguard *wireguard;
|
Wireguard *wireguard;
|
||||||
NetworkConfigSection *section;
|
ConfigSection *section;
|
||||||
|
|
||||||
uint8_t public_key[WG_KEY_LEN];
|
uint8_t public_key[WG_KEY_LEN];
|
||||||
uint8_t preshared_key[WG_KEY_LEN];
|
uint8_t preshared_key[WG_KEY_LEN];
|
||||||
|
|||||||
@ -21,14 +21,14 @@ AddressLabel *address_label_free(AddressLabel *label) {
|
|||||||
hashmap_remove(label->network->address_labels_by_section, label->section);
|
hashmap_remove(label->network->address_labels_by_section, label->section);
|
||||||
}
|
}
|
||||||
|
|
||||||
network_config_section_free(label->section);
|
config_section_free(label->section);
|
||||||
return mfree(label);
|
return mfree(label);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_NETWORK_SECTION_FUNCTIONS(AddressLabel, address_label_free);
|
DEFINE_SECTION_CLEANUP_FUNCTIONS(AddressLabel, address_label_free);
|
||||||
|
|
||||||
static int address_label_new_static(Network *network, const char *filename, unsigned section_line, AddressLabel **ret) {
|
static int address_label_new_static(Network *network, const char *filename, unsigned section_line, AddressLabel **ret) {
|
||||||
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
|
_cleanup_(config_section_freep) ConfigSection *n = NULL;
|
||||||
_cleanup_(address_label_freep) AddressLabel *label = NULL;
|
_cleanup_(address_label_freep) AddressLabel *label = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ static int address_label_new_static(Network *network, const char *filename, unsi
|
|||||||
assert(filename);
|
assert(filename);
|
||||||
assert(section_line > 0);
|
assert(section_line > 0);
|
||||||
|
|
||||||
r = network_config_section_new(filename, section_line, &n);
|
r = config_section_new(filename, section_line, &n);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ static int address_label_new_static(Network *network, const char *filename, unsi
|
|||||||
.label = UINT32_MAX,
|
.label = UINT32_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
r = hashmap_ensure_put(&network->address_labels_by_section, &network_config_hash_ops, label->section, label);
|
r = hashmap_ensure_put(&network->address_labels_by_section, &config_section_hash_ops, label->section, label);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@ typedef struct Request Request;
|
|||||||
|
|
||||||
typedef struct AddressLabel {
|
typedef struct AddressLabel {
|
||||||
Network *network;
|
Network *network;
|
||||||
NetworkConfigSection *section;
|
ConfigSection *section;
|
||||||
|
|
||||||
uint32_t label;
|
uint32_t label;
|
||||||
struct in6_addr prefix;
|
struct in6_addr prefix;
|
||||||
|
|||||||
@ -77,7 +77,7 @@ int address_new(Address **ret) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int address_new_static(Network *network, const char *filename, unsigned section_line, Address **ret) {
|
static int address_new_static(Network *network, const char *filename, unsigned section_line, Address **ret) {
|
||||||
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
|
_cleanup_(config_section_freep) ConfigSection *n = NULL;
|
||||||
_cleanup_(address_freep) Address *address = NULL;
|
_cleanup_(address_freep) Address *address = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ static int address_new_static(Network *network, const char *filename, unsigned s
|
|||||||
assert(filename);
|
assert(filename);
|
||||||
assert(section_line > 0);
|
assert(section_line > 0);
|
||||||
|
|
||||||
r = network_config_section_new(filename, section_line, &n);
|
r = config_section_new(filename, section_line, &n);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -107,7 +107,7 @@ static int address_new_static(Network *network, const char *filename, unsigned s
|
|||||||
address->section = TAKE_PTR(n);
|
address->section = TAKE_PTR(n);
|
||||||
address->source = NETWORK_CONFIG_SOURCE_STATIC;
|
address->source = NETWORK_CONFIG_SOURCE_STATIC;
|
||||||
|
|
||||||
r = ordered_hashmap_ensure_put(&network->addresses_by_section, &network_config_hash_ops, address->section, address);
|
r = ordered_hashmap_ensure_put(&network->addresses_by_section, &config_section_hash_ops, address->section, address);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -134,7 +134,7 @@ Address *address_free(Address *address) {
|
|||||||
|
|
||||||
sd_ipv4acd_unref(address->acd);
|
sd_ipv4acd_unref(address->acd);
|
||||||
|
|
||||||
network_config_section_free(address->section);
|
config_section_free(address->section);
|
||||||
free(address->label);
|
free(address->label);
|
||||||
return mfree(address);
|
return mfree(address);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,7 +22,7 @@ typedef int (*address_ready_callback_t)(Address *address);
|
|||||||
struct Address {
|
struct Address {
|
||||||
Link *link;
|
Link *link;
|
||||||
Network *network;
|
Network *network;
|
||||||
NetworkConfigSection *section;
|
ConfigSection *section;
|
||||||
NetworkConfigSource source;
|
NetworkConfigSource source;
|
||||||
NetworkConfigState state;
|
NetworkConfigState state;
|
||||||
union in_addr_union provider; /* DHCP server or router address */
|
union in_addr_union provider; /* DHCP server or router address */
|
||||||
@ -72,7 +72,7 @@ int address_dup(const Address *src, Address **ret);
|
|||||||
bool address_is_ready(const Address *a);
|
bool address_is_ready(const Address *a);
|
||||||
void address_set_broadcast(Address *a);
|
void address_set_broadcast(Address *a);
|
||||||
|
|
||||||
DEFINE_NETWORK_SECTION_FUNCTIONS(Address, address_free);
|
DEFINE_SECTION_CLEANUP_FUNCTIONS(Address, address_free);
|
||||||
|
|
||||||
int link_drop_addresses(Link *link);
|
int link_drop_addresses(Link *link);
|
||||||
int link_drop_foreign_addresses(Link *link);
|
int link_drop_foreign_addresses(Link *link);
|
||||||
|
|||||||
@ -32,13 +32,13 @@ BridgeFDB *bridge_fdb_free(BridgeFDB *fdb) {
|
|||||||
hashmap_remove(fdb->network->bridge_fdb_entries_by_section, fdb->section);
|
hashmap_remove(fdb->network->bridge_fdb_entries_by_section, fdb->section);
|
||||||
}
|
}
|
||||||
|
|
||||||
network_config_section_free(fdb->section);
|
config_section_free(fdb->section);
|
||||||
|
|
||||||
free(fdb->outgoing_ifname);
|
free(fdb->outgoing_ifname);
|
||||||
return mfree(fdb);
|
return mfree(fdb);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_NETWORK_SECTION_FUNCTIONS(BridgeFDB, bridge_fdb_free);
|
DEFINE_SECTION_CLEANUP_FUNCTIONS(BridgeFDB, bridge_fdb_free);
|
||||||
|
|
||||||
/* create a new FDB entry or get an existing one. */
|
/* create a new FDB entry or get an existing one. */
|
||||||
static int bridge_fdb_new_static(
|
static int bridge_fdb_new_static(
|
||||||
@ -47,7 +47,7 @@ static int bridge_fdb_new_static(
|
|||||||
unsigned section_line,
|
unsigned section_line,
|
||||||
BridgeFDB **ret) {
|
BridgeFDB **ret) {
|
||||||
|
|
||||||
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
|
_cleanup_(config_section_freep) ConfigSection *n = NULL;
|
||||||
_cleanup_(bridge_fdb_freep) BridgeFDB *fdb = NULL;
|
_cleanup_(bridge_fdb_freep) BridgeFDB *fdb = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ static int bridge_fdb_new_static(
|
|||||||
assert(filename);
|
assert(filename);
|
||||||
assert(section_line > 0);
|
assert(section_line > 0);
|
||||||
|
|
||||||
r = network_config_section_new(filename, section_line, &n);
|
r = config_section_new(filename, section_line, &n);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ static int bridge_fdb_new_static(
|
|||||||
.ntf_flags = NEIGHBOR_CACHE_ENTRY_FLAGS_SELF,
|
.ntf_flags = NEIGHBOR_CACHE_ENTRY_FLAGS_SELF,
|
||||||
};
|
};
|
||||||
|
|
||||||
r = hashmap_ensure_put(&network->bridge_fdb_entries_by_section, &network_config_hash_ops, fdb->section, fdb);
|
r = hashmap_ensure_put(&network->bridge_fdb_entries_by_section, &config_section_hash_ops, fdb->section, fdb);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|||||||
@ -27,7 +27,7 @@ typedef enum NeighborCacheEntryFlags {
|
|||||||
|
|
||||||
typedef struct BridgeFDB {
|
typedef struct BridgeFDB {
|
||||||
Network *network;
|
Network *network;
|
||||||
NetworkConfigSection *section;
|
ConfigSection *section;
|
||||||
|
|
||||||
uint32_t vni;
|
uint32_t vni;
|
||||||
|
|
||||||
|
|||||||
@ -24,12 +24,12 @@ BridgeMDB *bridge_mdb_free(BridgeMDB *mdb) {
|
|||||||
hashmap_remove(mdb->network->bridge_mdb_entries_by_section, mdb->section);
|
hashmap_remove(mdb->network->bridge_mdb_entries_by_section, mdb->section);
|
||||||
}
|
}
|
||||||
|
|
||||||
network_config_section_free(mdb->section);
|
config_section_free(mdb->section);
|
||||||
|
|
||||||
return mfree(mdb);
|
return mfree(mdb);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_NETWORK_SECTION_FUNCTIONS(BridgeMDB, bridge_mdb_free);
|
DEFINE_SECTION_CLEANUP_FUNCTIONS(BridgeMDB, bridge_mdb_free);
|
||||||
|
|
||||||
/* create a new MDB entry or get an existing one. */
|
/* create a new MDB entry or get an existing one. */
|
||||||
static int bridge_mdb_new_static(
|
static int bridge_mdb_new_static(
|
||||||
@ -38,7 +38,7 @@ static int bridge_mdb_new_static(
|
|||||||
unsigned section_line,
|
unsigned section_line,
|
||||||
BridgeMDB **ret) {
|
BridgeMDB **ret) {
|
||||||
|
|
||||||
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
|
_cleanup_(config_section_freep) ConfigSection *n = NULL;
|
||||||
_cleanup_(bridge_mdb_freep) BridgeMDB *mdb = NULL;
|
_cleanup_(bridge_mdb_freep) BridgeMDB *mdb = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ static int bridge_mdb_new_static(
|
|||||||
assert(filename);
|
assert(filename);
|
||||||
assert(section_line > 0);
|
assert(section_line > 0);
|
||||||
|
|
||||||
r = network_config_section_new(filename, section_line, &n);
|
r = config_section_new(filename, section_line, &n);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ static int bridge_mdb_new_static(
|
|||||||
.section = TAKE_PTR(n),
|
.section = TAKE_PTR(n),
|
||||||
};
|
};
|
||||||
|
|
||||||
r = hashmap_ensure_put(&network->bridge_mdb_entries_by_section, &network_config_hash_ops, mdb->section, mdb);
|
r = hashmap_ensure_put(&network->bridge_mdb_entries_by_section, &config_section_hash_ops, mdb->section, mdb);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@ typedef struct Request Request;
|
|||||||
|
|
||||||
typedef struct BridgeMDB {
|
typedef struct BridgeMDB {
|
||||||
Network *network;
|
Network *network;
|
||||||
NetworkConfigSection *section;
|
ConfigSection *section;
|
||||||
|
|
||||||
int family;
|
int family;
|
||||||
union in_addr_union group_addr;
|
union in_addr_union group_addr;
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
#include "networkd-network.h"
|
#include "networkd-network.h"
|
||||||
#include "networkd-util.h"
|
#include "networkd-util.h"
|
||||||
|
|
||||||
DEFINE_NETWORK_SECTION_FUNCTIONS(DHCPStaticLease, dhcp_static_lease_free);
|
DEFINE_SECTION_CLEANUP_FUNCTIONS(DHCPStaticLease, dhcp_static_lease_free);
|
||||||
|
|
||||||
DHCPStaticLease *dhcp_static_lease_free(DHCPStaticLease *static_lease) {
|
DHCPStaticLease *dhcp_static_lease_free(DHCPStaticLease *static_lease) {
|
||||||
if (!static_lease)
|
if (!static_lease)
|
||||||
@ -16,7 +16,7 @@ DHCPStaticLease *dhcp_static_lease_free(DHCPStaticLease *static_lease) {
|
|||||||
if (static_lease->network && static_lease->section)
|
if (static_lease->network && static_lease->section)
|
||||||
hashmap_remove(static_lease->network->dhcp_static_leases_by_section, static_lease->section);
|
hashmap_remove(static_lease->network->dhcp_static_leases_by_section, static_lease->section);
|
||||||
|
|
||||||
network_config_section_free(static_lease->section);
|
config_section_free(static_lease->section);
|
||||||
free(static_lease->client_id);
|
free(static_lease->client_id);
|
||||||
return mfree(static_lease);
|
return mfree(static_lease);
|
||||||
}
|
}
|
||||||
@ -35,7 +35,7 @@ static int dhcp_static_lease_new(DHCPStaticLease **ret) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int lease_new_static(Network *network, const char *filename, unsigned section_line, DHCPStaticLease **ret) {
|
static int lease_new_static(Network *network, const char *filename, unsigned section_line, DHCPStaticLease **ret) {
|
||||||
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
|
_cleanup_(config_section_freep) ConfigSection *n = NULL;
|
||||||
_cleanup_(dhcp_static_lease_freep) DHCPStaticLease *static_lease = NULL;
|
_cleanup_(dhcp_static_lease_freep) DHCPStaticLease *static_lease = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ static int lease_new_static(Network *network, const char *filename, unsigned sec
|
|||||||
assert(section_line > 0);
|
assert(section_line > 0);
|
||||||
assert(ret);
|
assert(ret);
|
||||||
|
|
||||||
r = network_config_section_new(filename, section_line, &n);
|
r = config_section_new(filename, section_line, &n);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ static int lease_new_static(Network *network, const char *filename, unsigned sec
|
|||||||
|
|
||||||
static_lease->network = network;
|
static_lease->network = network;
|
||||||
static_lease->section = TAKE_PTR(n);
|
static_lease->section = TAKE_PTR(n);
|
||||||
r = hashmap_ensure_put(&network->dhcp_static_leases_by_section, &network_config_hash_ops, static_lease->section, static_lease);
|
r = hashmap_ensure_put(&network->dhcp_static_leases_by_section, &config_section_hash_ops, static_lease->section, static_lease);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|||||||
@ -8,11 +8,11 @@
|
|||||||
#include "in-addr-util.h"
|
#include "in-addr-util.h"
|
||||||
|
|
||||||
typedef struct Network Network;
|
typedef struct Network Network;
|
||||||
typedef struct NetworkConfigSection NetworkConfigSection;
|
typedef struct ConfigSection ConfigSection;
|
||||||
|
|
||||||
typedef struct DHCPStaticLease {
|
typedef struct DHCPStaticLease {
|
||||||
Network *network;
|
Network *network;
|
||||||
NetworkConfigSection *section;
|
ConfigSection *section;
|
||||||
|
|
||||||
struct in_addr address;
|
struct in_addr address;
|
||||||
uint8_t *client_id;
|
uint8_t *client_id;
|
||||||
|
|||||||
@ -2549,6 +2549,8 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
|
|||||||
r = ethtool_get_driver(&manager->ethtool_fd, link->ifname, &link->driver);
|
r = ethtool_get_driver(&manager->ethtool_fd, link->ifname, &link->driver);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_link_debug_errno(link, r, "Failed to get driver, continuing without: %m");
|
log_link_debug_errno(link, r, "Failed to get driver, continuing without: %m");
|
||||||
|
else
|
||||||
|
log_link_debug(link, "Found driver: %s", strna(link->driver));
|
||||||
|
|
||||||
if (streq_ptr(link->driver, "dsa")) {
|
if (streq_ptr(link->driver, "dsa")) {
|
||||||
uint32_t dsa_master_ifindex;
|
uint32_t dsa_master_ifindex;
|
||||||
|
|||||||
@ -19,7 +19,7 @@ Neighbor *neighbor_free(Neighbor *neighbor) {
|
|||||||
hashmap_remove(neighbor->network->neighbors_by_section, neighbor->section);
|
hashmap_remove(neighbor->network->neighbors_by_section, neighbor->section);
|
||||||
}
|
}
|
||||||
|
|
||||||
network_config_section_free(neighbor->section);
|
config_section_free(neighbor->section);
|
||||||
|
|
||||||
if (neighbor->link)
|
if (neighbor->link)
|
||||||
set_remove(neighbor->link->neighbors, neighbor);
|
set_remove(neighbor->link->neighbors, neighbor);
|
||||||
@ -27,10 +27,10 @@ Neighbor *neighbor_free(Neighbor *neighbor) {
|
|||||||
return mfree(neighbor);
|
return mfree(neighbor);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_NETWORK_SECTION_FUNCTIONS(Neighbor, neighbor_free);
|
DEFINE_SECTION_CLEANUP_FUNCTIONS(Neighbor, neighbor_free);
|
||||||
|
|
||||||
static int neighbor_new_static(Network *network, const char *filename, unsigned section_line, Neighbor **ret) {
|
static int neighbor_new_static(Network *network, const char *filename, unsigned section_line, Neighbor **ret) {
|
||||||
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
|
_cleanup_(config_section_freep) ConfigSection *n = NULL;
|
||||||
_cleanup_(neighbor_freep) Neighbor *neighbor = NULL;
|
_cleanup_(neighbor_freep) Neighbor *neighbor = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ static int neighbor_new_static(Network *network, const char *filename, unsigned
|
|||||||
assert(filename);
|
assert(filename);
|
||||||
assert(section_line > 0);
|
assert(section_line > 0);
|
||||||
|
|
||||||
r = network_config_section_new(filename, section_line, &n);
|
r = config_section_new(filename, section_line, &n);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ static int neighbor_new_static(Network *network, const char *filename, unsigned
|
|||||||
.source = NETWORK_CONFIG_SOURCE_STATIC,
|
.source = NETWORK_CONFIG_SOURCE_STATIC,
|
||||||
};
|
};
|
||||||
|
|
||||||
r = hashmap_ensure_put(&network->neighbors_by_section, &network_config_hash_ops, neighbor->section, neighbor);
|
r = hashmap_ensure_put(&network->neighbors_by_section, &config_section_hash_ops, neighbor->section, neighbor);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,7 @@ typedef struct Request Request;
|
|||||||
typedef struct Neighbor {
|
typedef struct Neighbor {
|
||||||
Network *network;
|
Network *network;
|
||||||
Link *link;
|
Link *link;
|
||||||
NetworkConfigSection *section;
|
ConfigSection *section;
|
||||||
NetworkConfigSource source;
|
NetworkConfigSource source;
|
||||||
NetworkConfigState state;
|
NetworkConfigState state;
|
||||||
|
|
||||||
|
|||||||
@ -73,15 +73,15 @@ Link.Unmanaged, config_parse_bool,
|
|||||||
Link.ActivationPolicy, config_parse_activation_policy, 0, offsetof(Network, activation_policy)
|
Link.ActivationPolicy, config_parse_activation_policy, 0, offsetof(Network, activation_policy)
|
||||||
Link.RequiredForOnline, config_parse_required_for_online, 0, 0
|
Link.RequiredForOnline, config_parse_required_for_online, 0, 0
|
||||||
Link.RequiredFamilyForOnline, config_parse_required_family_for_online, 0, offsetof(Network, required_family_for_online)
|
Link.RequiredFamilyForOnline, config_parse_required_family_for_online, 0, offsetof(Network, required_family_for_online)
|
||||||
SR-IOV.VirtualFunction, config_parse_sr_iov_uint32, 0, 0
|
SR-IOV.VirtualFunction, config_parse_sr_iov_uint32, 0, offsetof(Network, sr_iov_by_section)
|
||||||
SR-IOV.VLANId, config_parse_sr_iov_uint32, 0, 0
|
SR-IOV.VLANId, config_parse_sr_iov_uint32, 0, offsetof(Network, sr_iov_by_section)
|
||||||
SR-IOV.QualityOfService, config_parse_sr_iov_uint32, 0, 0
|
SR-IOV.QualityOfService, config_parse_sr_iov_uint32, 0, offsetof(Network, sr_iov_by_section)
|
||||||
SR-IOV.VLANProtocol, config_parse_sr_iov_vlan_proto, 0, 0
|
SR-IOV.VLANProtocol, config_parse_sr_iov_vlan_proto, 0, offsetof(Network, sr_iov_by_section)
|
||||||
SR-IOV.MACSpoofCheck, config_parse_sr_iov_boolean, 0, 0
|
SR-IOV.MACSpoofCheck, config_parse_sr_iov_boolean, 0, offsetof(Network, sr_iov_by_section)
|
||||||
SR-IOV.QueryReceiveSideScaling, config_parse_sr_iov_boolean, 0, 0
|
SR-IOV.QueryReceiveSideScaling, config_parse_sr_iov_boolean, 0, offsetof(Network, sr_iov_by_section)
|
||||||
SR-IOV.Trust, config_parse_sr_iov_boolean, 0, 0
|
SR-IOV.Trust, config_parse_sr_iov_boolean, 0, offsetof(Network, sr_iov_by_section)
|
||||||
SR-IOV.LinkState, config_parse_sr_iov_link_state, 0, 0
|
SR-IOV.LinkState, config_parse_sr_iov_link_state, 0, offsetof(Network, sr_iov_by_section)
|
||||||
SR-IOV.MACAddress, config_parse_sr_iov_mac, 0, 0
|
SR-IOV.MACAddress, config_parse_sr_iov_mac, 0, offsetof(Network, sr_iov_by_section)
|
||||||
Network.Description, config_parse_string, 0, offsetof(Network, description)
|
Network.Description, config_parse_string, 0, offsetof(Network, description)
|
||||||
Network.KeepMaster, config_parse_bool, 0, offsetof(Network, keep_master)
|
Network.KeepMaster, config_parse_bool, 0, offsetof(Network, keep_master)
|
||||||
Network.BatmanAdvanced, config_parse_ifname, 0, offsetof(Network, batadv_name)
|
Network.BatmanAdvanced, config_parse_ifname, 0, offsetof(Network, batadv_name)
|
||||||
|
|||||||
@ -321,7 +321,9 @@ int network_verify(Network *network) {
|
|||||||
network_drop_invalid_route_prefixes(network);
|
network_drop_invalid_route_prefixes(network);
|
||||||
network_drop_invalid_routing_policy_rules(network);
|
network_drop_invalid_routing_policy_rules(network);
|
||||||
network_drop_invalid_traffic_control(network);
|
network_drop_invalid_traffic_control(network);
|
||||||
network_drop_invalid_sr_iov(network);
|
r = sr_iov_drop_invalid_sections(UINT32_MAX, network->sr_iov_by_section);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
network_drop_invalid_static_leases(network);
|
network_drop_invalid_static_leases(network);
|
||||||
|
|
||||||
network_adjust_dhcp_server(network);
|
network_adjust_dhcp_server(network);
|
||||||
|
|||||||
@ -27,7 +27,7 @@ NextHop *nexthop_free(NextHop *nexthop) {
|
|||||||
hashmap_remove(nexthop->network->nexthops_by_section, nexthop->section);
|
hashmap_remove(nexthop->network->nexthops_by_section, nexthop->section);
|
||||||
}
|
}
|
||||||
|
|
||||||
network_config_section_free(nexthop->section);
|
config_section_free(nexthop->section);
|
||||||
|
|
||||||
if (nexthop->link) {
|
if (nexthop->link) {
|
||||||
set_remove(nexthop->link->nexthops, nexthop);
|
set_remove(nexthop->link->nexthops, nexthop);
|
||||||
@ -48,7 +48,7 @@ NextHop *nexthop_free(NextHop *nexthop) {
|
|||||||
return mfree(nexthop);
|
return mfree(nexthop);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_NETWORK_SECTION_FUNCTIONS(NextHop, nexthop_free);
|
DEFINE_SECTION_CLEANUP_FUNCTIONS(NextHop, nexthop_free);
|
||||||
|
|
||||||
static int nexthop_new(NextHop **ret) {
|
static int nexthop_new(NextHop **ret) {
|
||||||
_cleanup_(nexthop_freep) NextHop *nexthop = NULL;
|
_cleanup_(nexthop_freep) NextHop *nexthop = NULL;
|
||||||
@ -68,7 +68,7 @@ static int nexthop_new(NextHop **ret) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int nexthop_new_static(Network *network, const char *filename, unsigned section_line, NextHop **ret) {
|
static int nexthop_new_static(Network *network, const char *filename, unsigned section_line, NextHop **ret) {
|
||||||
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
|
_cleanup_(config_section_freep) ConfigSection *n = NULL;
|
||||||
_cleanup_(nexthop_freep) NextHop *nexthop = NULL;
|
_cleanup_(nexthop_freep) NextHop *nexthop = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ static int nexthop_new_static(Network *network, const char *filename, unsigned s
|
|||||||
assert(filename);
|
assert(filename);
|
||||||
assert(section_line > 0);
|
assert(section_line > 0);
|
||||||
|
|
||||||
r = network_config_section_new(filename, section_line, &n);
|
r = config_section_new(filename, section_line, &n);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ static int nexthop_new_static(Network *network, const char *filename, unsigned s
|
|||||||
nexthop->section = TAKE_PTR(n);
|
nexthop->section = TAKE_PTR(n);
|
||||||
nexthop->source = NETWORK_CONFIG_SOURCE_STATIC;
|
nexthop->source = NETWORK_CONFIG_SOURCE_STATIC;
|
||||||
|
|
||||||
r = hashmap_ensure_put(&network->nexthops_by_section, &network_config_hash_ops, nexthop->section, nexthop);
|
r = hashmap_ensure_put(&network->nexthops_by_section, &config_section_hash_ops, nexthop->section, nexthop);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|||||||
@ -22,7 +22,7 @@ typedef struct NextHop {
|
|||||||
Network *network;
|
Network *network;
|
||||||
Manager *manager;
|
Manager *manager;
|
||||||
Link *link;
|
Link *link;
|
||||||
NetworkConfigSection *section;
|
ConfigSection *section;
|
||||||
NetworkConfigSource source;
|
NetworkConfigSource source;
|
||||||
NetworkConfigState state;
|
NetworkConfigState state;
|
||||||
|
|
||||||
|
|||||||
@ -69,16 +69,16 @@ Prefix *prefix_free(Prefix *prefix) {
|
|||||||
hashmap_remove(prefix->network->prefixes_by_section, prefix->section);
|
hashmap_remove(prefix->network->prefixes_by_section, prefix->section);
|
||||||
}
|
}
|
||||||
|
|
||||||
network_config_section_free(prefix->section);
|
config_section_free(prefix->section);
|
||||||
set_free(prefix->tokens);
|
set_free(prefix->tokens);
|
||||||
|
|
||||||
return mfree(prefix);
|
return mfree(prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_NETWORK_SECTION_FUNCTIONS(Prefix, prefix_free);
|
DEFINE_SECTION_CLEANUP_FUNCTIONS(Prefix, prefix_free);
|
||||||
|
|
||||||
static int prefix_new_static(Network *network, const char *filename, unsigned section_line, Prefix **ret) {
|
static int prefix_new_static(Network *network, const char *filename, unsigned section_line, Prefix **ret) {
|
||||||
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
|
_cleanup_(config_section_freep) ConfigSection *n = NULL;
|
||||||
_cleanup_(prefix_freep) Prefix *prefix = NULL;
|
_cleanup_(prefix_freep) Prefix *prefix = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -87,7 +87,7 @@ static int prefix_new_static(Network *network, const char *filename, unsigned se
|
|||||||
assert(filename);
|
assert(filename);
|
||||||
assert(section_line > 0);
|
assert(section_line > 0);
|
||||||
|
|
||||||
r = network_config_section_new(filename, section_line, &n);
|
r = config_section_new(filename, section_line, &n);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ static int prefix_new_static(Network *network, const char *filename, unsigned se
|
|||||||
.address_auto_configuration = true,
|
.address_auto_configuration = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
r = hashmap_ensure_put(&network->prefixes_by_section, &network_config_hash_ops, prefix->section, prefix);
|
r = hashmap_ensure_put(&network->prefixes_by_section, &config_section_hash_ops, prefix->section, prefix);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -128,15 +128,15 @@ RoutePrefix *route_prefix_free(RoutePrefix *prefix) {
|
|||||||
hashmap_remove(prefix->network->route_prefixes_by_section, prefix->section);
|
hashmap_remove(prefix->network->route_prefixes_by_section, prefix->section);
|
||||||
}
|
}
|
||||||
|
|
||||||
network_config_section_free(prefix->section);
|
config_section_free(prefix->section);
|
||||||
|
|
||||||
return mfree(prefix);
|
return mfree(prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_NETWORK_SECTION_FUNCTIONS(RoutePrefix, route_prefix_free);
|
DEFINE_SECTION_CLEANUP_FUNCTIONS(RoutePrefix, route_prefix_free);
|
||||||
|
|
||||||
static int route_prefix_new_static(Network *network, const char *filename, unsigned section_line, RoutePrefix **ret) {
|
static int route_prefix_new_static(Network *network, const char *filename, unsigned section_line, RoutePrefix **ret) {
|
||||||
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
|
_cleanup_(config_section_freep) ConfigSection *n = NULL;
|
||||||
_cleanup_(route_prefix_freep) RoutePrefix *prefix = NULL;
|
_cleanup_(route_prefix_freep) RoutePrefix *prefix = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -145,7 +145,7 @@ static int route_prefix_new_static(Network *network, const char *filename, unsig
|
|||||||
assert(filename);
|
assert(filename);
|
||||||
assert(section_line > 0);
|
assert(section_line > 0);
|
||||||
|
|
||||||
r = network_config_section_new(filename, section_line, &n);
|
r = config_section_new(filename, section_line, &n);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -166,7 +166,7 @@ static int route_prefix_new_static(Network *network, const char *filename, unsig
|
|||||||
.lifetime = RADV_DEFAULT_VALID_LIFETIME_USEC,
|
.lifetime = RADV_DEFAULT_VALID_LIFETIME_USEC,
|
||||||
};
|
};
|
||||||
|
|
||||||
r = hashmap_ensure_put(&network->route_prefixes_by_section, &network_config_hash_ops, prefix->section, prefix);
|
r = hashmap_ensure_put(&network->route_prefixes_by_section, &config_section_hash_ops, prefix->section, prefix);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|||||||
@ -29,7 +29,7 @@ typedef enum RADVPrefixDelegation {
|
|||||||
|
|
||||||
typedef struct Prefix {
|
typedef struct Prefix {
|
||||||
Network *network;
|
Network *network;
|
||||||
NetworkConfigSection *section;
|
ConfigSection *section;
|
||||||
|
|
||||||
struct in6_addr prefix;
|
struct in6_addr prefix;
|
||||||
uint8_t prefixlen;
|
uint8_t prefixlen;
|
||||||
@ -46,7 +46,7 @@ typedef struct Prefix {
|
|||||||
|
|
||||||
typedef struct RoutePrefix {
|
typedef struct RoutePrefix {
|
||||||
Network *network;
|
Network *network;
|
||||||
NetworkConfigSection *section;
|
ConfigSection *section;
|
||||||
|
|
||||||
struct in6_addr prefix;
|
struct in6_addr prefix;
|
||||||
uint8_t prefixlen;
|
uint8_t prefixlen;
|
||||||
|
|||||||
@ -47,7 +47,7 @@ int route_new(Route **ret) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int route_new_static(Network *network, const char *filename, unsigned section_line, Route **ret) {
|
static int route_new_static(Network *network, const char *filename, unsigned section_line, Route **ret) {
|
||||||
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
|
_cleanup_(config_section_freep) ConfigSection *n = NULL;
|
||||||
_cleanup_(route_freep) Route *route = NULL;
|
_cleanup_(route_freep) Route *route = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ static int route_new_static(Network *network, const char *filename, unsigned sec
|
|||||||
assert(filename);
|
assert(filename);
|
||||||
assert(section_line > 0);
|
assert(section_line > 0);
|
||||||
|
|
||||||
r = network_config_section_new(filename, section_line, &n);
|
r = config_section_new(filename, section_line, &n);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -78,7 +78,7 @@ static int route_new_static(Network *network, const char *filename, unsigned sec
|
|||||||
route->section = TAKE_PTR(n);
|
route->section = TAKE_PTR(n);
|
||||||
route->source = NETWORK_CONFIG_SOURCE_STATIC;
|
route->source = NETWORK_CONFIG_SOURCE_STATIC;
|
||||||
|
|
||||||
r = hashmap_ensure_put(&network->routes_by_section, &network_config_hash_ops, route->section, route);
|
r = hashmap_ensure_put(&network->routes_by_section, &config_section_hash_ops, route->section, route);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -95,7 +95,7 @@ Route *route_free(Route *route) {
|
|||||||
hashmap_remove(route->network->routes_by_section, route->section);
|
hashmap_remove(route->network->routes_by_section, route->section);
|
||||||
}
|
}
|
||||||
|
|
||||||
network_config_section_free(route->section);
|
config_section_free(route->section);
|
||||||
|
|
||||||
if (route->link)
|
if (route->link)
|
||||||
set_remove(route->link->routes, route);
|
set_remove(route->link->routes, route);
|
||||||
|
|||||||
@ -19,7 +19,7 @@ typedef struct Route {
|
|||||||
Link *link;
|
Link *link;
|
||||||
Manager *manager;
|
Manager *manager;
|
||||||
Network *network;
|
Network *network;
|
||||||
NetworkConfigSection *section;
|
ConfigSection *section;
|
||||||
NetworkConfigSource source;
|
NetworkConfigSource source;
|
||||||
NetworkConfigState state;
|
NetworkConfigState state;
|
||||||
union in_addr_union provider; /* DHCP server or router address */
|
union in_addr_union provider; /* DHCP server or router address */
|
||||||
@ -74,7 +74,7 @@ extern const struct hash_ops route_hash_ops;
|
|||||||
|
|
||||||
int route_new(Route **ret);
|
int route_new(Route **ret);
|
||||||
Route *route_free(Route *route);
|
Route *route_free(Route *route);
|
||||||
DEFINE_NETWORK_SECTION_FUNCTIONS(Route, route_free);
|
DEFINE_SECTION_CLEANUP_FUNCTIONS(Route, route_free);
|
||||||
int route_dup(const Route *src, Route **ret);
|
int route_dup(const Route *src, Route **ret);
|
||||||
|
|
||||||
int route_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link, const char *error_msg);
|
int route_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link, const char *error_msg);
|
||||||
|
|||||||
@ -54,14 +54,14 @@ RoutingPolicyRule *routing_policy_rule_free(RoutingPolicyRule *rule) {
|
|||||||
if (rule->manager)
|
if (rule->manager)
|
||||||
set_remove(rule->manager->rules, rule);
|
set_remove(rule->manager->rules, rule);
|
||||||
|
|
||||||
network_config_section_free(rule->section);
|
config_section_free(rule->section);
|
||||||
free(rule->iif);
|
free(rule->iif);
|
||||||
free(rule->oif);
|
free(rule->oif);
|
||||||
|
|
||||||
return mfree(rule);
|
return mfree(rule);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_NETWORK_SECTION_FUNCTIONS(RoutingPolicyRule, routing_policy_rule_free);
|
DEFINE_SECTION_CLEANUP_FUNCTIONS(RoutingPolicyRule, routing_policy_rule_free);
|
||||||
|
|
||||||
static int routing_policy_rule_new(RoutingPolicyRule **ret) {
|
static int routing_policy_rule_new(RoutingPolicyRule **ret) {
|
||||||
RoutingPolicyRule *rule;
|
RoutingPolicyRule *rule;
|
||||||
@ -86,7 +86,7 @@ static int routing_policy_rule_new(RoutingPolicyRule **ret) {
|
|||||||
|
|
||||||
static int routing_policy_rule_new_static(Network *network, const char *filename, unsigned section_line, RoutingPolicyRule **ret) {
|
static int routing_policy_rule_new_static(Network *network, const char *filename, unsigned section_line, RoutingPolicyRule **ret) {
|
||||||
_cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule = NULL;
|
_cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule = NULL;
|
||||||
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
|
_cleanup_(config_section_freep) ConfigSection *n = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(network);
|
assert(network);
|
||||||
@ -94,7 +94,7 @@ static int routing_policy_rule_new_static(Network *network, const char *filename
|
|||||||
assert(filename);
|
assert(filename);
|
||||||
assert(section_line > 0);
|
assert(section_line > 0);
|
||||||
|
|
||||||
r = network_config_section_new(filename, section_line, &n);
|
r = config_section_new(filename, section_line, &n);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -113,7 +113,7 @@ static int routing_policy_rule_new_static(Network *network, const char *filename
|
|||||||
rule->source = NETWORK_CONFIG_SOURCE_STATIC;
|
rule->source = NETWORK_CONFIG_SOURCE_STATIC;
|
||||||
rule->protocol = RTPROT_STATIC;
|
rule->protocol = RTPROT_STATIC;
|
||||||
|
|
||||||
r = hashmap_ensure_put(&network->rules_by_section, &network_config_hash_ops, rule->section, rule);
|
r = hashmap_ensure_put(&network->rules_by_section, &config_section_hash_ops, rule->section, rule);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|||||||
@ -17,7 +17,7 @@ typedef struct Request Request;
|
|||||||
typedef struct RoutingPolicyRule {
|
typedef struct RoutingPolicyRule {
|
||||||
Manager *manager;
|
Manager *manager;
|
||||||
Network *network;
|
Network *network;
|
||||||
NetworkConfigSection *section;
|
ConfigSection *section;
|
||||||
NetworkConfigSource source;
|
NetworkConfigSource source;
|
||||||
NetworkConfigState state;
|
NetworkConfigState state;
|
||||||
|
|
||||||
|
|||||||
@ -1,82 +1,10 @@
|
|||||||
/* SPDX-License-Identifier: LGPL-2.1-or-later
|
/* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
* Copyright © 2020 VMware, Inc. */
|
* Copyright © 2020 VMware, Inc. */
|
||||||
|
|
||||||
#include "alloc-util.h"
|
|
||||||
#include "netlink-util.h"
|
#include "netlink-util.h"
|
||||||
|
#include "networkd-link.h"
|
||||||
#include "networkd-manager.h"
|
#include "networkd-manager.h"
|
||||||
#include "networkd-sriov.h"
|
#include "networkd-sriov.h"
|
||||||
#include "parse-util.h"
|
|
||||||
#include "set.h"
|
|
||||||
#include "string-util.h"
|
|
||||||
|
|
||||||
static int sr_iov_new(SRIOV **ret) {
|
|
||||||
SRIOV *sr_iov;
|
|
||||||
|
|
||||||
sr_iov = new(SRIOV, 1);
|
|
||||||
if (!sr_iov)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
*sr_iov = (SRIOV) {
|
|
||||||
.vf = UINT32_MAX,
|
|
||||||
.vlan_proto = ETH_P_8021Q,
|
|
||||||
.vf_spoof_check_setting = -1,
|
|
||||||
.trust = -1,
|
|
||||||
.query_rss = -1,
|
|
||||||
.link_state = _SR_IOV_LINK_STATE_INVALID,
|
|
||||||
};
|
|
||||||
|
|
||||||
*ret = TAKE_PTR(sr_iov);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sr_iov_new_static(Network *network, const char *filename, unsigned section_line, SRIOV **ret) {
|
|
||||||
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
|
|
||||||
_cleanup_(sr_iov_freep) SRIOV *sr_iov = NULL;
|
|
||||||
SRIOV *existing = NULL;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(network);
|
|
||||||
assert(ret);
|
|
||||||
assert(filename);
|
|
||||||
assert(section_line > 0);
|
|
||||||
|
|
||||||
r = network_config_section_new(filename, section_line, &n);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
existing = ordered_hashmap_get(network->sr_iov_by_section, n);
|
|
||||||
if (existing) {
|
|
||||||
*ret = existing;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = sr_iov_new(&sr_iov);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
sr_iov->network = network;
|
|
||||||
sr_iov->section = TAKE_PTR(n);
|
|
||||||
|
|
||||||
r = ordered_hashmap_ensure_put(&network->sr_iov_by_section, &network_config_hash_ops, sr_iov->section, sr_iov);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
*ret = TAKE_PTR(sr_iov);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
SRIOV *sr_iov_free(SRIOV *sr_iov) {
|
|
||||||
if (!sr_iov)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (sr_iov->network && sr_iov->section)
|
|
||||||
ordered_hashmap_remove(sr_iov->network->sr_iov_by_section, sr_iov->section);
|
|
||||||
|
|
||||||
network_config_section_free(sr_iov->section);
|
|
||||||
|
|
||||||
return mfree(sr_iov);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sr_iov_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
static int sr_iov_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||||
int r;
|
int r;
|
||||||
@ -117,104 +45,16 @@ static int sr_iov_configure(Link *link, SRIOV *sr_iov) {
|
|||||||
|
|
||||||
r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
|
r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
|
return r;
|
||||||
|
|
||||||
r = sd_netlink_message_open_container(req, IFLA_VFINFO_LIST);
|
r = sr_iov_set_netlink_message(sr_iov, req);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not open IFLA_VFINFO_LIST container: %m");
|
return r;
|
||||||
|
|
||||||
r = sd_netlink_message_open_container(req, IFLA_VF_INFO);
|
|
||||||
if (r < 0)
|
|
||||||
return log_link_error_errno(link, r, "Could not open IFLA_VF_INFO container: %m");
|
|
||||||
|
|
||||||
if (!ether_addr_is_null(&sr_iov->mac)) {
|
|
||||||
struct ifla_vf_mac ivm = {
|
|
||||||
.vf = sr_iov->vf,
|
|
||||||
};
|
|
||||||
|
|
||||||
memcpy(ivm.mac, &sr_iov->mac, ETH_ALEN);
|
|
||||||
r = sd_netlink_message_append_data(req, IFLA_VF_MAC, &ivm, sizeof(struct ifla_vf_mac));
|
|
||||||
if (r < 0)
|
|
||||||
return log_link_error_errno(link, r, "Could not append IFLA_VF_MAC: %m");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sr_iov->vf_spoof_check_setting >= 0) {
|
|
||||||
struct ifla_vf_spoofchk ivs = {
|
|
||||||
.vf = sr_iov->vf,
|
|
||||||
.setting = sr_iov->vf_spoof_check_setting,
|
|
||||||
};
|
|
||||||
|
|
||||||
r = sd_netlink_message_append_data(req, IFLA_VF_SPOOFCHK, &ivs, sizeof(struct ifla_vf_spoofchk));
|
|
||||||
if (r < 0)
|
|
||||||
return log_link_error_errno(link, r, "Could not append IFLA_VF_SPOOFCHK: %m");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sr_iov->query_rss >= 0) {
|
|
||||||
struct ifla_vf_rss_query_en ivs = {
|
|
||||||
.vf = sr_iov->vf,
|
|
||||||
.setting = sr_iov->query_rss,
|
|
||||||
};
|
|
||||||
|
|
||||||
r = sd_netlink_message_append_data(req, IFLA_VF_RSS_QUERY_EN, &ivs, sizeof(struct ifla_vf_rss_query_en));
|
|
||||||
if (r < 0)
|
|
||||||
return log_link_error_errno(link, r, "Could not append IFLA_VF_RSS_QUERY_EN: %m");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sr_iov->trust >= 0) {
|
|
||||||
struct ifla_vf_trust ivt = {
|
|
||||||
.vf = sr_iov->vf,
|
|
||||||
.setting = sr_iov->trust,
|
|
||||||
};
|
|
||||||
|
|
||||||
r = sd_netlink_message_append_data(req, IFLA_VF_TRUST, &ivt, sizeof(struct ifla_vf_trust));
|
|
||||||
if (r < 0)
|
|
||||||
return log_link_error_errno(link, r, "Could not append IFLA_VF_TRUST: %m");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sr_iov->link_state >= 0) {
|
|
||||||
struct ifla_vf_link_state ivl = {
|
|
||||||
.vf = sr_iov->vf,
|
|
||||||
.link_state = sr_iov->link_state,
|
|
||||||
};
|
|
||||||
|
|
||||||
r = sd_netlink_message_append_data(req, IFLA_VF_LINK_STATE, &ivl, sizeof(struct ifla_vf_link_state));
|
|
||||||
if (r < 0)
|
|
||||||
return log_link_error_errno(link, r, "Could not append IFLA_VF_LINK_STATE: %m");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sr_iov->vlan > 0) {
|
|
||||||
/* Because of padding, first the buffer must be initialized with 0. */
|
|
||||||
struct ifla_vf_vlan_info ivvi = {};
|
|
||||||
ivvi.vf = sr_iov->vf;
|
|
||||||
ivvi.vlan = sr_iov->vlan;
|
|
||||||
ivvi.qos = sr_iov->qos;
|
|
||||||
ivvi.vlan_proto = htobe16(sr_iov->vlan_proto);
|
|
||||||
|
|
||||||
r = sd_netlink_message_open_container(req, IFLA_VF_VLAN_LIST);
|
|
||||||
if (r < 0)
|
|
||||||
return log_link_error_errno(link, r, "Could not open IFLA_VF_VLAN_LIST container: %m");
|
|
||||||
|
|
||||||
r = sd_netlink_message_append_data(req, IFLA_VF_VLAN_INFO, &ivvi, sizeof(struct ifla_vf_vlan_info));
|
|
||||||
if (r < 0)
|
|
||||||
return log_link_error_errno(link, r, "Could not append IFLA_VF_VLAN_INFO: %m");
|
|
||||||
|
|
||||||
r = sd_netlink_message_close_container(req);
|
|
||||||
if (r < 0)
|
|
||||||
return log_link_error_errno(link, r, "Could not close IFLA_VF_VLAN_LIST container: %m");
|
|
||||||
}
|
|
||||||
|
|
||||||
r = sd_netlink_message_close_container(req);
|
|
||||||
if (r < 0)
|
|
||||||
return log_link_error_errno(link, r, "Could not close IFLA_VF_INFO container: %m");
|
|
||||||
|
|
||||||
r = sd_netlink_message_close_container(req);
|
|
||||||
if (r < 0)
|
|
||||||
return log_link_error_errno(link, r, "Could not close IFLA_VFINFO_LIST container: %m");
|
|
||||||
|
|
||||||
r = netlink_call_async(link->manager->rtnl, NULL, req, sr_iov_handler,
|
r = netlink_call_async(link->manager->rtnl, NULL, req, sr_iov_handler,
|
||||||
link_netlink_destroy_callback, link);
|
link_netlink_destroy_callback, link);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
|
return r;
|
||||||
|
|
||||||
link_ref(link);
|
link_ref(link);
|
||||||
link->sr_iov_messages++;
|
link->sr_iov_messages++;
|
||||||
@ -239,7 +79,9 @@ int link_configure_sr_iov(Link *link) {
|
|||||||
ORDERED_HASHMAP_FOREACH(sr_iov, link->network->sr_iov_by_section) {
|
ORDERED_HASHMAP_FOREACH(sr_iov, link->network->sr_iov_by_section) {
|
||||||
r = sr_iov_configure(link, sr_iov);
|
r = sr_iov_configure(link, sr_iov);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return log_link_warning_errno(link, r,
|
||||||
|
"Failed to configure SR-IOV virtual function %"PRIu32": %m",
|
||||||
|
sr_iov->vf);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (link->sr_iov_messages == 0)
|
if (link->sr_iov_messages == 0)
|
||||||
@ -249,287 +91,3 @@ int link_configure_sr_iov(Link *link) {
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sr_iov_section_verify(SRIOV *sr_iov) {
|
|
||||||
assert(sr_iov);
|
|
||||||
|
|
||||||
if (section_is_invalid(sr_iov->section))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (sr_iov->vf == UINT32_MAX)
|
|
||||||
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
|
|
||||||
"%s: [SRIOV] section without VirtualFunction= field configured. "
|
|
||||||
"Ignoring [SRIOV] section from line %u.",
|
|
||||||
sr_iov->section->filename, sr_iov->section->line);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void network_drop_invalid_sr_iov(Network *network) {
|
|
||||||
SRIOV *sr_iov;
|
|
||||||
|
|
||||||
assert(network);
|
|
||||||
|
|
||||||
ORDERED_HASHMAP_FOREACH(sr_iov, network->sr_iov_by_section)
|
|
||||||
if (sr_iov_section_verify(sr_iov) < 0)
|
|
||||||
sr_iov_free(sr_iov);
|
|
||||||
}
|
|
||||||
|
|
||||||
int config_parse_sr_iov_uint32(
|
|
||||||
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_(sr_iov_free_or_set_invalidp) SRIOV *sr_iov = NULL;
|
|
||||||
Network *network = data;
|
|
||||||
uint32_t k;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(filename);
|
|
||||||
assert(lvalue);
|
|
||||||
assert(rvalue);
|
|
||||||
assert(data);
|
|
||||||
|
|
||||||
r = sr_iov_new_static(network, filename, section_line, &sr_iov);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (isempty(rvalue)) {
|
|
||||||
if (streq(lvalue, "VirtualFunction"))
|
|
||||||
sr_iov->vf = UINT32_MAX;
|
|
||||||
else if (streq(lvalue, "VLANId"))
|
|
||||||
sr_iov->vlan = 0;
|
|
||||||
else if (streq(lvalue, "QualityOfService"))
|
|
||||||
sr_iov->qos = 0;
|
|
||||||
else
|
|
||||||
assert_not_reached();
|
|
||||||
|
|
||||||
TAKE_PTR(sr_iov);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = safe_atou32(rvalue, &k);
|
|
||||||
if (r < 0) {
|
|
||||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
|
||||||
"Failed to parse SR-IOV '%s=', ignoring assignment: %s", lvalue, rvalue);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (streq(lvalue, "VLANId")) {
|
|
||||||
if (k == 0 || k > 4095) {
|
|
||||||
log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid SR-IOV VLANId: %d", k);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
sr_iov->vlan = k;
|
|
||||||
} else if (streq(lvalue, "VirtualFunction")) {
|
|
||||||
if (k >= INT_MAX) {
|
|
||||||
log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid SR-IOV virtual function: %d", k);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
sr_iov->vf = k;
|
|
||||||
} else if (streq(lvalue, "QualityOfService"))
|
|
||||||
sr_iov->qos = k;
|
|
||||||
else
|
|
||||||
assert_not_reached();
|
|
||||||
|
|
||||||
TAKE_PTR(sr_iov);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int config_parse_sr_iov_vlan_proto(
|
|
||||||
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_(sr_iov_free_or_set_invalidp) SRIOV *sr_iov = NULL;
|
|
||||||
Network *network = data;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(filename);
|
|
||||||
assert(lvalue);
|
|
||||||
assert(rvalue);
|
|
||||||
assert(data);
|
|
||||||
|
|
||||||
r = sr_iov_new_static(network, filename, section_line, &sr_iov);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (isempty(rvalue) || streq(rvalue, "802.1Q"))
|
|
||||||
sr_iov->vlan_proto = ETH_P_8021Q;
|
|
||||||
else if (streq(rvalue, "802.1ad"))
|
|
||||||
sr_iov->vlan_proto = ETH_P_8021AD;
|
|
||||||
else {
|
|
||||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
|
||||||
"Invalid SR-IOV '%s=', ignoring assignment: %s", lvalue, rvalue);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
TAKE_PTR(sr_iov);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int config_parse_sr_iov_link_state(
|
|
||||||
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_(sr_iov_free_or_set_invalidp) SRIOV *sr_iov = NULL;
|
|
||||||
Network *network = data;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(filename);
|
|
||||||
assert(lvalue);
|
|
||||||
assert(rvalue);
|
|
||||||
assert(data);
|
|
||||||
|
|
||||||
r = sr_iov_new_static(network, filename, section_line, &sr_iov);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
/* Unfortunately, SR_IOV_LINK_STATE_DISABLE is 2, not 0. So, we cannot use
|
|
||||||
* DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN() macro. */
|
|
||||||
|
|
||||||
if (isempty(rvalue)) {
|
|
||||||
sr_iov->link_state = _SR_IOV_LINK_STATE_INVALID;
|
|
||||||
TAKE_PTR(sr_iov);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (streq(rvalue, "auto")) {
|
|
||||||
sr_iov->link_state = SR_IOV_LINK_STATE_AUTO;
|
|
||||||
TAKE_PTR(sr_iov);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = parse_boolean(rvalue);
|
|
||||||
if (r < 0) {
|
|
||||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
|
||||||
"Failed to parse SR-IOV '%s=', ignoring assignment: %s", lvalue, rvalue);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sr_iov->link_state = r ? SR_IOV_LINK_STATE_ENABLE : SR_IOV_LINK_STATE_DISABLE;
|
|
||||||
TAKE_PTR(sr_iov);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int config_parse_sr_iov_boolean(
|
|
||||||
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_(sr_iov_free_or_set_invalidp) SRIOV *sr_iov = NULL;
|
|
||||||
Network *network = data;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(filename);
|
|
||||||
assert(lvalue);
|
|
||||||
assert(rvalue);
|
|
||||||
assert(data);
|
|
||||||
|
|
||||||
r = sr_iov_new_static(network, filename, section_line, &sr_iov);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (isempty(rvalue)) {
|
|
||||||
if (streq(lvalue, "MACSpoofCheck"))
|
|
||||||
sr_iov->vf_spoof_check_setting = -1;
|
|
||||||
else if (streq(lvalue, "QueryReceiveSideScaling"))
|
|
||||||
sr_iov->query_rss = -1;
|
|
||||||
else if (streq(lvalue, "Trust"))
|
|
||||||
sr_iov->trust = -1;
|
|
||||||
else
|
|
||||||
assert_not_reached();
|
|
||||||
|
|
||||||
TAKE_PTR(sr_iov);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = parse_boolean(rvalue);
|
|
||||||
if (r < 0) {
|
|
||||||
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse '%s=', ignoring: %s", lvalue, rvalue);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (streq(lvalue, "MACSpoofCheck"))
|
|
||||||
sr_iov->vf_spoof_check_setting = r;
|
|
||||||
else if (streq(lvalue, "QueryReceiveSideScaling"))
|
|
||||||
sr_iov->query_rss = r;
|
|
||||||
else if (streq(lvalue, "Trust"))
|
|
||||||
sr_iov->trust = r;
|
|
||||||
else
|
|
||||||
assert_not_reached();
|
|
||||||
|
|
||||||
TAKE_PTR(sr_iov);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int config_parse_sr_iov_mac(
|
|
||||||
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_(sr_iov_free_or_set_invalidp) SRIOV *sr_iov = NULL;
|
|
||||||
Network *network = data;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(filename);
|
|
||||||
assert(lvalue);
|
|
||||||
assert(rvalue);
|
|
||||||
assert(data);
|
|
||||||
|
|
||||||
r = sr_iov_new_static(network, filename, section_line, &sr_iov);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (isempty(rvalue)) {
|
|
||||||
sr_iov->mac = ETHER_ADDR_NULL;
|
|
||||||
TAKE_PTR(sr_iov);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = parse_ether_addr(rvalue, &sr_iov->mac);
|
|
||||||
if (r < 0) {
|
|
||||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
|
||||||
"Failed to parse SR-IOV '%s=', ignoring assignment: %s", lvalue, rvalue);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
TAKE_PTR(sr_iov);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -2,45 +2,8 @@
|
|||||||
* Copyright © 2020 VMware, Inc. */
|
* Copyright © 2020 VMware, Inc. */
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <linux/if_link.h>
|
#include "netif-sriov.h"
|
||||||
|
|
||||||
#include "conf-parser.h"
|
typedef struct Link Link;
|
||||||
#include "ether-addr-util.h"
|
|
||||||
#include "networkd-link.h"
|
|
||||||
#include "networkd-network.h"
|
|
||||||
#include "networkd-util.h"
|
|
||||||
|
|
||||||
typedef enum SRIOVLinkState {
|
|
||||||
SR_IOV_LINK_STATE_AUTO = IFLA_VF_LINK_STATE_AUTO,
|
|
||||||
SR_IOV_LINK_STATE_ENABLE = IFLA_VF_LINK_STATE_ENABLE,
|
|
||||||
SR_IOV_LINK_STATE_DISABLE = IFLA_VF_LINK_STATE_DISABLE,
|
|
||||||
_SR_IOV_LINK_STATE_MAX,
|
|
||||||
_SR_IOV_LINK_STATE_INVALID = -EINVAL,
|
|
||||||
} SRIOVLinkState;
|
|
||||||
|
|
||||||
typedef struct SRIOV {
|
|
||||||
NetworkConfigSection *section;
|
|
||||||
Network *network;
|
|
||||||
|
|
||||||
uint32_t vf; /* 0 - 2147483646 */
|
|
||||||
uint32_t vlan; /* 0 - 4095, 0 disables VLAN filter */
|
|
||||||
uint32_t qos;
|
|
||||||
uint16_t vlan_proto; /* ETH_P_8021Q or ETH_P_8021AD */
|
|
||||||
int vf_spoof_check_setting;
|
|
||||||
int query_rss;
|
|
||||||
int trust;
|
|
||||||
SRIOVLinkState link_state;
|
|
||||||
struct ether_addr mac;
|
|
||||||
} SRIOV;
|
|
||||||
|
|
||||||
SRIOV *sr_iov_free(SRIOV *sr_iov);
|
|
||||||
int link_configure_sr_iov(Link *link);
|
int link_configure_sr_iov(Link *link);
|
||||||
void network_drop_invalid_sr_iov(Network *network);
|
|
||||||
|
|
||||||
DEFINE_NETWORK_SECTION_FUNCTIONS(SRIOV, sr_iov_free);
|
|
||||||
|
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_sr_iov_uint32);
|
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_sr_iov_boolean);
|
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_sr_iov_link_state);
|
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_sr_iov_vlan_proto);
|
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_sr_iov_mac);
|
|
||||||
|
|||||||
@ -243,50 +243,6 @@ int config_parse_mud_url(
|
|||||||
return free_and_replace(*url, unescaped);
|
return free_and_replace(*url, unescaped);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void network_config_hash_func(const NetworkConfigSection *c, struct siphash *state) {
|
|
||||||
siphash24_compress_string(c->filename, state);
|
|
||||||
siphash24_compress(&c->line, sizeof(c->line), state);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int network_config_compare_func(const NetworkConfigSection *x, const NetworkConfigSection *y) {
|
|
||||||
int r;
|
|
||||||
|
|
||||||
r = strcmp(x->filename, y->filename);
|
|
||||||
if (r != 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
return CMP(x->line, y->line);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_HASH_OPS(network_config_hash_ops, NetworkConfigSection, network_config_hash_func, network_config_compare_func);
|
|
||||||
|
|
||||||
int network_config_section_new(const char *filename, unsigned line, NetworkConfigSection **s) {
|
|
||||||
NetworkConfigSection *cs;
|
|
||||||
|
|
||||||
cs = malloc0(offsetof(NetworkConfigSection, filename) + strlen(filename) + 1);
|
|
||||||
if (!cs)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
strcpy(cs->filename, filename);
|
|
||||||
cs->line = line;
|
|
||||||
|
|
||||||
*s = TAKE_PTR(cs);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned hashmap_find_free_section_line(Hashmap *hashmap) {
|
|
||||||
NetworkConfigSection *cs;
|
|
||||||
unsigned n = 0;
|
|
||||||
void *entry;
|
|
||||||
|
|
||||||
HASHMAP_FOREACH_KEY(entry, cs, hashmap)
|
|
||||||
if (n < cs->line)
|
|
||||||
n = cs->line;
|
|
||||||
|
|
||||||
return n + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int log_link_message_full_errno(Link *link, sd_netlink_message *m, int level, int err, const char *msg) {
|
int log_link_message_full_errno(Link *link, sd_netlink_message *m, int level, int err, const char *msg) {
|
||||||
const char *err_msg = NULL;
|
const char *err_msg = NULL;
|
||||||
|
|
||||||
|
|||||||
@ -13,12 +13,6 @@
|
|||||||
|
|
||||||
typedef struct Link Link;
|
typedef struct Link Link;
|
||||||
|
|
||||||
typedef struct NetworkConfigSection {
|
|
||||||
unsigned line;
|
|
||||||
bool invalid;
|
|
||||||
char filename[];
|
|
||||||
} NetworkConfigSection;
|
|
||||||
|
|
||||||
typedef enum NetworkConfigSource {
|
typedef enum NetworkConfigSource {
|
||||||
NETWORK_CONFIG_SOURCE_FOREIGN, /* configured by kernel */
|
NETWORK_CONFIG_SOURCE_FOREIGN, /* configured by kernel */
|
||||||
NETWORK_CONFIG_SOURCE_STATIC,
|
NETWORK_CONFIG_SOURCE_STATIC,
|
||||||
@ -141,37 +135,6 @@ AddressFamily dhcp_deprecated_address_family_from_string(const char *s) _pure_;
|
|||||||
const char *dhcp_lease_server_type_to_string(sd_dhcp_lease_server_type_t t) _const_;
|
const char *dhcp_lease_server_type_to_string(sd_dhcp_lease_server_type_t t) _const_;
|
||||||
sd_dhcp_lease_server_type_t dhcp_lease_server_type_from_string(const char *s) _pure_;
|
sd_dhcp_lease_server_type_t dhcp_lease_server_type_from_string(const char *s) _pure_;
|
||||||
|
|
||||||
static inline NetworkConfigSection* network_config_section_free(NetworkConfigSection *cs) {
|
|
||||||
return mfree(cs);
|
|
||||||
}
|
|
||||||
DEFINE_TRIVIAL_CLEANUP_FUNC(NetworkConfigSection*, network_config_section_free);
|
|
||||||
|
|
||||||
int network_config_section_new(const char *filename, unsigned line, NetworkConfigSection **s);
|
|
||||||
extern const struct hash_ops network_config_hash_ops;
|
|
||||||
unsigned hashmap_find_free_section_line(Hashmap *hashmap);
|
|
||||||
|
|
||||||
static inline bool section_is_invalid(NetworkConfigSection *section) {
|
|
||||||
/* If this returns false, then it does _not_ mean the section is valid. */
|
|
||||||
|
|
||||||
if (!section)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return section->invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DEFINE_NETWORK_SECTION_FUNCTIONS(type, free_func) \
|
|
||||||
static inline type* free_func##_or_set_invalid(type *p) { \
|
|
||||||
assert(p); \
|
|
||||||
\
|
|
||||||
if (p->section) \
|
|
||||||
p->section->invalid = true; \
|
|
||||||
else \
|
|
||||||
free_func(p); \
|
|
||||||
return NULL; \
|
|
||||||
} \
|
|
||||||
DEFINE_TRIVIAL_CLEANUP_FUNC(type*, free_func); \
|
|
||||||
DEFINE_TRIVIAL_CLEANUP_FUNC(type*, free_func##_or_set_invalid);
|
|
||||||
|
|
||||||
int log_link_message_full_errno(Link *link, sd_netlink_message *m, int level, int err, const char *msg);
|
int log_link_message_full_errno(Link *link, sd_netlink_message *m, int level, int err, const char *msg);
|
||||||
#define log_link_message_error_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_ERR, err, msg)
|
#define log_link_message_error_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_ERR, err, msg)
|
||||||
#define log_link_message_warning_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_WARNING, err, msg)
|
#define log_link_message_warning_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_WARNING, err, msg)
|
||||||
|
|||||||
@ -77,7 +77,7 @@ static int qdisc_new(QDiscKind kind, QDisc **ret) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, unsigned section_line, QDisc **ret) {
|
int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, unsigned section_line, QDisc **ret) {
|
||||||
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
|
_cleanup_(config_section_freep) ConfigSection *n = NULL;
|
||||||
_cleanup_(qdisc_freep) QDisc *qdisc = NULL;
|
_cleanup_(qdisc_freep) QDisc *qdisc = NULL;
|
||||||
TrafficControl *existing;
|
TrafficControl *existing;
|
||||||
QDisc *q = NULL;
|
QDisc *q = NULL;
|
||||||
@ -88,7 +88,7 @@ int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, uns
|
|||||||
assert(filename);
|
assert(filename);
|
||||||
assert(section_line > 0);
|
assert(section_line > 0);
|
||||||
|
|
||||||
r = network_config_section_new(filename, section_line, &n);
|
r = config_section_new(filename, section_line, &n);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -126,7 +126,7 @@ int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, uns
|
|||||||
qdisc->network = network;
|
qdisc->network = network;
|
||||||
qdisc->section = TAKE_PTR(n);
|
qdisc->section = TAKE_PTR(n);
|
||||||
|
|
||||||
r = ordered_hashmap_ensure_put(&network->tc_by_section, &network_config_hash_ops, qdisc->section, TC(qdisc));
|
r = ordered_hashmap_ensure_put(&network->tc_by_section, &config_section_hash_ops, qdisc->section, TC(qdisc));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -141,7 +141,7 @@ QDisc* qdisc_free(QDisc *qdisc) {
|
|||||||
if (qdisc->network && qdisc->section)
|
if (qdisc->network && qdisc->section)
|
||||||
ordered_hashmap_remove(qdisc->network->tc_by_section, qdisc->section);
|
ordered_hashmap_remove(qdisc->network->tc_by_section, qdisc->section);
|
||||||
|
|
||||||
network_config_section_free(qdisc->section);
|
config_section_free(qdisc->section);
|
||||||
|
|
||||||
free(qdisc->tca_kind);
|
free(qdisc->tca_kind);
|
||||||
return mfree(qdisc);
|
return mfree(qdisc);
|
||||||
|
|||||||
@ -37,7 +37,7 @@ typedef enum QDiscKind {
|
|||||||
typedef struct QDisc {
|
typedef struct QDisc {
|
||||||
TrafficControl meta;
|
TrafficControl meta;
|
||||||
|
|
||||||
NetworkConfigSection *section;
|
ConfigSection *section;
|
||||||
Network *network;
|
Network *network;
|
||||||
|
|
||||||
int family;
|
int family;
|
||||||
@ -80,7 +80,7 @@ int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, uns
|
|||||||
int qdisc_configure(Link *link, QDisc *qdisc);
|
int qdisc_configure(Link *link, QDisc *qdisc);
|
||||||
int qdisc_section_verify(QDisc *qdisc, bool *has_root, bool *has_clsact);
|
int qdisc_section_verify(QDisc *qdisc, bool *has_root, bool *has_clsact);
|
||||||
|
|
||||||
DEFINE_NETWORK_SECTION_FUNCTIONS(QDisc, qdisc_free);
|
DEFINE_SECTION_CLEANUP_FUNCTIONS(QDisc, qdisc_free);
|
||||||
|
|
||||||
DEFINE_TC_CAST(QDISC, QDisc);
|
DEFINE_TC_CAST(QDISC, QDisc);
|
||||||
|
|
||||||
|
|||||||
@ -45,7 +45,7 @@ static int tclass_new(TClassKind kind, TClass **ret) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int tclass_new_static(TClassKind kind, Network *network, const char *filename, unsigned section_line, TClass **ret) {
|
int tclass_new_static(TClassKind kind, Network *network, const char *filename, unsigned section_line, TClass **ret) {
|
||||||
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
|
_cleanup_(config_section_freep) ConfigSection *n = NULL;
|
||||||
_cleanup_(tclass_freep) TClass *tclass = NULL;
|
_cleanup_(tclass_freep) TClass *tclass = NULL;
|
||||||
TrafficControl *existing;
|
TrafficControl *existing;
|
||||||
int r;
|
int r;
|
||||||
@ -55,7 +55,7 @@ int tclass_new_static(TClassKind kind, Network *network, const char *filename, u
|
|||||||
assert(filename);
|
assert(filename);
|
||||||
assert(section_line > 0);
|
assert(section_line > 0);
|
||||||
|
|
||||||
r = network_config_section_new(filename, section_line, &n);
|
r = config_section_new(filename, section_line, &n);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ int tclass_new_static(TClassKind kind, Network *network, const char *filename, u
|
|||||||
tclass->network = network;
|
tclass->network = network;
|
||||||
tclass->section = TAKE_PTR(n);
|
tclass->section = TAKE_PTR(n);
|
||||||
|
|
||||||
r = ordered_hashmap_ensure_put(&network->tc_by_section, &network_config_hash_ops, tclass->section, tclass);
|
r = ordered_hashmap_ensure_put(&network->tc_by_section, &config_section_hash_ops, tclass->section, tclass);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -97,7 +97,7 @@ TClass* tclass_free(TClass *tclass) {
|
|||||||
if (tclass->network && tclass->section)
|
if (tclass->network && tclass->section)
|
||||||
ordered_hashmap_remove(tclass->network->tc_by_section, tclass->section);
|
ordered_hashmap_remove(tclass->network->tc_by_section, tclass->section);
|
||||||
|
|
||||||
network_config_section_free(tclass->section);
|
config_section_free(tclass->section);
|
||||||
|
|
||||||
return mfree(tclass);
|
return mfree(tclass);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,7 +19,7 @@ typedef enum TClassKind {
|
|||||||
typedef struct TClass {
|
typedef struct TClass {
|
||||||
TrafficControl meta;
|
TrafficControl meta;
|
||||||
|
|
||||||
NetworkConfigSection *section;
|
ConfigSection *section;
|
||||||
Network *network;
|
Network *network;
|
||||||
|
|
||||||
uint32_t classid;
|
uint32_t classid;
|
||||||
@ -59,7 +59,7 @@ int tclass_new_static(TClassKind kind, Network *network, const char *filename, u
|
|||||||
int tclass_configure(Link *link, TClass *tclass);
|
int tclass_configure(Link *link, TClass *tclass);
|
||||||
int tclass_section_verify(TClass *tclass);
|
int tclass_section_verify(TClass *tclass);
|
||||||
|
|
||||||
DEFINE_NETWORK_SECTION_FUNCTIONS(TClass, tclass_free);
|
DEFINE_SECTION_CLEANUP_FUNCTIONS(TClass, tclass_free);
|
||||||
|
|
||||||
DEFINE_TC_CAST(TCLASS, TClass);
|
DEFINE_TC_CAST(TCLASS, TClass);
|
||||||
|
|
||||||
|
|||||||
@ -156,10 +156,10 @@ int bus_introspect_implementations(
|
|||||||
if (impl != main_impl)
|
if (impl != main_impl)
|
||||||
bus_introspect_implementation(&intro, impl);
|
bus_introspect_implementation(&intro, impl);
|
||||||
|
|
||||||
_cleanup_set_free_ Set *nodes = NULL;
|
_cleanup_ordered_set_free_ OrderedSet *nodes = NULL;
|
||||||
|
|
||||||
for (size_t i = 0; impl->children && impl->children[i]; i++) {
|
for (size_t i = 0; impl->children && impl->children[i]; i++) {
|
||||||
r = set_put_strdup(&nodes, impl->children[i]->path);
|
r = ordered_set_put_strdup(&nodes, impl->children[i]->path);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -573,6 +573,50 @@ int config_parse_many(
|
|||||||
return config_parse_many_files(conf_files, files, sections, lookup, table, flags, userdata, ret_stats_by_path);
|
return config_parse_many_files(conf_files, files, sections, lookup, table, flags, userdata, ret_stats_by_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void config_section_hash_func(const ConfigSection *c, struct siphash *state) {
|
||||||
|
siphash24_compress_string(c->filename, state);
|
||||||
|
siphash24_compress(&c->line, sizeof(c->line), state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int config_section_compare_func(const ConfigSection *x, const ConfigSection *y) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = strcmp(x->filename, y->filename);
|
||||||
|
if (r != 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
return CMP(x->line, y->line);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_HASH_OPS(config_section_hash_ops, ConfigSection, config_section_hash_func, config_section_compare_func);
|
||||||
|
|
||||||
|
int config_section_new(const char *filename, unsigned line, ConfigSection **s) {
|
||||||
|
ConfigSection *cs;
|
||||||
|
|
||||||
|
cs = malloc0(offsetof(ConfigSection, filename) + strlen(filename) + 1);
|
||||||
|
if (!cs)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
strcpy(cs->filename, filename);
|
||||||
|
cs->line = line;
|
||||||
|
|
||||||
|
*s = TAKE_PTR(cs);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned hashmap_find_free_section_line(Hashmap *hashmap) {
|
||||||
|
ConfigSection *cs;
|
||||||
|
unsigned n = 0;
|
||||||
|
void *entry;
|
||||||
|
|
||||||
|
HASHMAP_FOREACH_KEY(entry, cs, hashmap)
|
||||||
|
if (n < cs->line)
|
||||||
|
n = cs->line;
|
||||||
|
|
||||||
|
return n + 1;
|
||||||
|
}
|
||||||
|
|
||||||
#define DEFINE_PARSER(type, vartype, conv_func) \
|
#define DEFINE_PARSER(type, vartype, conv_func) \
|
||||||
DEFINE_CONFIG_PARSE_PTR(config_parse_##type, conv_func, vartype, "Failed to parse " #type " value")
|
DEFINE_CONFIG_PARSE_PTR(config_parse_##type, conv_func, vartype, "Failed to parse " #type " value")
|
||||||
|
|
||||||
|
|||||||
@ -114,6 +114,43 @@ int config_parse_many(
|
|||||||
void *userdata,
|
void *userdata,
|
||||||
Hashmap **ret_stats_by_path); /* possibly NULL */
|
Hashmap **ret_stats_by_path); /* possibly NULL */
|
||||||
|
|
||||||
|
typedef struct ConfigSection {
|
||||||
|
unsigned line;
|
||||||
|
bool invalid;
|
||||||
|
char filename[];
|
||||||
|
} ConfigSection;
|
||||||
|
|
||||||
|
static inline ConfigSection* config_section_free(ConfigSection *cs) {
|
||||||
|
return mfree(cs);
|
||||||
|
}
|
||||||
|
DEFINE_TRIVIAL_CLEANUP_FUNC(ConfigSection*, config_section_free);
|
||||||
|
|
||||||
|
int config_section_new(const char *filename, unsigned line, ConfigSection **s);
|
||||||
|
extern const struct hash_ops config_section_hash_ops;
|
||||||
|
unsigned hashmap_find_free_section_line(Hashmap *hashmap);
|
||||||
|
|
||||||
|
static inline bool section_is_invalid(ConfigSection *section) {
|
||||||
|
/* If this returns false, then it does _not_ mean the section is valid. */
|
||||||
|
|
||||||
|
if (!section)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return section->invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEFINE_SECTION_CLEANUP_FUNCTIONS(type, free_func) \
|
||||||
|
static inline type* free_func##_or_set_invalid(type *p) { \
|
||||||
|
assert(p); \
|
||||||
|
\
|
||||||
|
if (p->section) \
|
||||||
|
p->section->invalid = true; \
|
||||||
|
else \
|
||||||
|
free_func(p); \
|
||||||
|
return NULL; \
|
||||||
|
} \
|
||||||
|
DEFINE_TRIVIAL_CLEANUP_FUNC(type*, free_func); \
|
||||||
|
DEFINE_TRIVIAL_CLEANUP_FUNC(type*, free_func##_or_set_invalid);
|
||||||
|
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_int);
|
CONFIG_PARSER_PROTOTYPE(config_parse_int);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_unsigned);
|
CONFIG_PARSER_PROTOTYPE(config_parse_unsigned);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_long);
|
CONFIG_PARSER_PROTOTYPE(config_parse_long);
|
||||||
|
|||||||
@ -224,6 +224,8 @@ shared_sources = files('''
|
|||||||
net-condition.h
|
net-condition.h
|
||||||
netif-naming-scheme.c
|
netif-naming-scheme.c
|
||||||
netif-naming-scheme.h
|
netif-naming-scheme.h
|
||||||
|
netif-sriov.c
|
||||||
|
netif-sriov.h
|
||||||
netif-util.c
|
netif-util.c
|
||||||
netif-util.h
|
netif-util.h
|
||||||
nscd-flush.h
|
nscd-flush.h
|
||||||
|
|||||||
631
src/shared/netif-sriov.c
Normal file
631
src/shared/netif-sriov.c
Normal file
@ -0,0 +1,631 @@
|
|||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
|
||||||
|
#include "alloc-util.h"
|
||||||
|
#include "device-util.h"
|
||||||
|
#include "netlink-util.h"
|
||||||
|
#include "netif-sriov.h"
|
||||||
|
#include "parse-util.h"
|
||||||
|
#include "set.h"
|
||||||
|
#include "stdio-util.h"
|
||||||
|
#include "string-util.h"
|
||||||
|
|
||||||
|
static int sr_iov_new(SRIOV **ret) {
|
||||||
|
SRIOV *sr_iov;
|
||||||
|
|
||||||
|
assert(ret);
|
||||||
|
|
||||||
|
sr_iov = new(SRIOV, 1);
|
||||||
|
if (!sr_iov)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
*sr_iov = (SRIOV) {
|
||||||
|
.vf = UINT32_MAX,
|
||||||
|
.vlan_proto = ETH_P_8021Q,
|
||||||
|
.vf_spoof_check_setting = -1,
|
||||||
|
.trust = -1,
|
||||||
|
.query_rss = -1,
|
||||||
|
.link_state = _SR_IOV_LINK_STATE_INVALID,
|
||||||
|
};
|
||||||
|
|
||||||
|
*ret = TAKE_PTR(sr_iov);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sr_iov_new_static(OrderedHashmap **sr_iov_by_section, const char *filename, unsigned section_line, SRIOV **ret) {
|
||||||
|
_cleanup_(config_section_freep) ConfigSection *n = NULL;
|
||||||
|
_cleanup_(sr_iov_freep) SRIOV *sr_iov = NULL;
|
||||||
|
SRIOV *existing = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(sr_iov_by_section);
|
||||||
|
assert(filename);
|
||||||
|
assert(section_line > 0);
|
||||||
|
assert(ret);
|
||||||
|
|
||||||
|
r = config_section_new(filename, section_line, &n);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
existing = ordered_hashmap_get(*sr_iov_by_section, n);
|
||||||
|
if (existing) {
|
||||||
|
*ret = existing;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sr_iov_new(&sr_iov);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = ordered_hashmap_ensure_put(sr_iov_by_section, &config_section_hash_ops, n, sr_iov);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
sr_iov->section = TAKE_PTR(n);
|
||||||
|
sr_iov->sr_iov_by_section = *sr_iov_by_section;
|
||||||
|
|
||||||
|
*ret = TAKE_PTR(sr_iov);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRIOV *sr_iov_free(SRIOV *sr_iov) {
|
||||||
|
if (!sr_iov)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (sr_iov->sr_iov_by_section && sr_iov->section)
|
||||||
|
ordered_hashmap_remove(sr_iov->sr_iov_by_section, sr_iov->section);
|
||||||
|
|
||||||
|
config_section_free(sr_iov->section);
|
||||||
|
|
||||||
|
return mfree(sr_iov);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sr_iov_set_netlink_message(SRIOV *sr_iov, sd_netlink_message *req) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(sr_iov);
|
||||||
|
assert(req);
|
||||||
|
|
||||||
|
r = sd_netlink_message_open_container(req, IFLA_VFINFO_LIST);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = sd_netlink_message_open_container(req, IFLA_VF_INFO);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (!ether_addr_is_null(&sr_iov->mac)) {
|
||||||
|
struct ifla_vf_mac ivm = {
|
||||||
|
.vf = sr_iov->vf,
|
||||||
|
};
|
||||||
|
|
||||||
|
memcpy(ivm.mac, &sr_iov->mac, ETH_ALEN);
|
||||||
|
r = sd_netlink_message_append_data(req, IFLA_VF_MAC, &ivm, sizeof(struct ifla_vf_mac));
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sr_iov->vf_spoof_check_setting >= 0) {
|
||||||
|
struct ifla_vf_spoofchk ivs = {
|
||||||
|
.vf = sr_iov->vf,
|
||||||
|
.setting = sr_iov->vf_spoof_check_setting,
|
||||||
|
};
|
||||||
|
|
||||||
|
r = sd_netlink_message_append_data(req, IFLA_VF_SPOOFCHK, &ivs, sizeof(struct ifla_vf_spoofchk));
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sr_iov->query_rss >= 0) {
|
||||||
|
struct ifla_vf_rss_query_en ivs = {
|
||||||
|
.vf = sr_iov->vf,
|
||||||
|
.setting = sr_iov->query_rss,
|
||||||
|
};
|
||||||
|
|
||||||
|
r = sd_netlink_message_append_data(req, IFLA_VF_RSS_QUERY_EN, &ivs, sizeof(struct ifla_vf_rss_query_en));
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sr_iov->trust >= 0) {
|
||||||
|
struct ifla_vf_trust ivt = {
|
||||||
|
.vf = sr_iov->vf,
|
||||||
|
.setting = sr_iov->trust,
|
||||||
|
};
|
||||||
|
|
||||||
|
r = sd_netlink_message_append_data(req, IFLA_VF_TRUST, &ivt, sizeof(struct ifla_vf_trust));
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sr_iov->link_state >= 0) {
|
||||||
|
struct ifla_vf_link_state ivl = {
|
||||||
|
.vf = sr_iov->vf,
|
||||||
|
.link_state = sr_iov->link_state,
|
||||||
|
};
|
||||||
|
|
||||||
|
r = sd_netlink_message_append_data(req, IFLA_VF_LINK_STATE, &ivl, sizeof(struct ifla_vf_link_state));
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sr_iov->vlan > 0) {
|
||||||
|
/* Because of padding, first the buffer must be initialized with 0. */
|
||||||
|
struct ifla_vf_vlan_info ivvi = {};
|
||||||
|
ivvi.vf = sr_iov->vf;
|
||||||
|
ivvi.vlan = sr_iov->vlan;
|
||||||
|
ivvi.qos = sr_iov->qos;
|
||||||
|
ivvi.vlan_proto = htobe16(sr_iov->vlan_proto);
|
||||||
|
|
||||||
|
r = sd_netlink_message_open_container(req, IFLA_VF_VLAN_LIST);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = sd_netlink_message_append_data(req, IFLA_VF_VLAN_INFO, &ivvi, sizeof(struct ifla_vf_vlan_info));
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = sd_netlink_message_close_container(req);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sd_netlink_message_close_container(req);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = sd_netlink_message_close_container(req);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sr_iov_get_num_vfs(sd_device *device, uint32_t *ret) {
|
||||||
|
const char *str;
|
||||||
|
uint32_t n;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(device);
|
||||||
|
assert(ret);
|
||||||
|
|
||||||
|
r = sd_device_get_sysattr_value(device, "device/sriov_numvfs", &str);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = safe_atou32(str, &n);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
*ret = n;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sr_iov_set_num_vfs(sd_device *device, uint32_t num_vfs, OrderedHashmap *sr_iov_by_section) {
|
||||||
|
char val[DECIMAL_STR_MAX(uint32_t)];
|
||||||
|
const char *str;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(device);
|
||||||
|
|
||||||
|
if (num_vfs == UINT32_MAX) {
|
||||||
|
uint32_t current_num_vfs;
|
||||||
|
SRIOV *sr_iov;
|
||||||
|
|
||||||
|
/* If the number of virtual functions is not specified, then use the maximum number of VF + 1. */
|
||||||
|
|
||||||
|
num_vfs = 0;
|
||||||
|
ORDERED_HASHMAP_FOREACH(sr_iov, sr_iov_by_section)
|
||||||
|
num_vfs = MAX(num_vfs, sr_iov->vf + 1);
|
||||||
|
|
||||||
|
if (num_vfs == 0) /* No VF is configured. */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
r = sr_iov_get_num_vfs(device, ¤t_num_vfs);
|
||||||
|
if (r < 0)
|
||||||
|
return log_device_debug_errno(device, r, "Failed to get the current number of SR-IOV virtual functions: %m");
|
||||||
|
|
||||||
|
/* Enough VFs already exist. */
|
||||||
|
if (num_vfs <= current_num_vfs)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
} else if (num_vfs == 0) {
|
||||||
|
r = sd_device_set_sysattr_value(device, "device/sriov_numvfs", "0");
|
||||||
|
if (r < 0)
|
||||||
|
log_device_debug_errno(device, r, "Failed to write device/sriov_numvfs sysfs attribute, ignoring: %m");
|
||||||
|
|
||||||
|
/* Gracefully handle the error in disabling VFs when the interface does not support SR-IOV. */
|
||||||
|
return r == -ENOENT ? 0 : r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* So, the interface does not have enough VFs. Before increasing the number of VFs, check the
|
||||||
|
* maximum allowed number of VFs from the sriov_totalvfs sysattr. Note that the sysattr
|
||||||
|
* currently exists only for PCI drivers. Hence, ignore -ENOENT.
|
||||||
|
* TODO: netdevsim provides the information in debugfs. */
|
||||||
|
r = sd_device_get_sysattr_value(device, "device/sriov_totalvfs", &str);
|
||||||
|
if (r >= 0) {
|
||||||
|
uint32_t max_num_vfs;
|
||||||
|
|
||||||
|
r = safe_atou32(str, &max_num_vfs);
|
||||||
|
if (r < 0)
|
||||||
|
return log_device_debug_errno(device, r, "Failed to parse device/sriov_totalvfs sysfs attribute '%s': %m", str);
|
||||||
|
|
||||||
|
if (num_vfs > max_num_vfs)
|
||||||
|
return log_device_debug_errno(device, SYNTHETIC_ERRNO(ERANGE),
|
||||||
|
"Specified number of virtual functions is out of range. "
|
||||||
|
"The maximum allowed value is %"PRIu32".",
|
||||||
|
max_num_vfs);
|
||||||
|
|
||||||
|
} else if (r != -ENOENT) /* Currently, only PCI driver has the attribute. */
|
||||||
|
return log_device_debug_errno(device, r, "Failed to read device/sriov_totalvfs sysfs attribute: %m");
|
||||||
|
|
||||||
|
xsprintf(val, "%"PRIu32, num_vfs);
|
||||||
|
r = sd_device_set_sysattr_value(device, "device/sriov_numvfs", val);
|
||||||
|
if (r == -EBUSY) {
|
||||||
|
/* Some devices e.g. netdevsim refuse to set sriov_numvfs if it has non-zero value. */
|
||||||
|
r = sd_device_set_sysattr_value(device, "device/sriov_numvfs", "0");
|
||||||
|
if (r >= 0)
|
||||||
|
r = sd_device_set_sysattr_value(device, "device/sriov_numvfs", val);
|
||||||
|
}
|
||||||
|
if (r < 0)
|
||||||
|
return log_device_debug_errno(device, r, "Failed to write device/sriov_numvfs sysfs attribute: %m");
|
||||||
|
|
||||||
|
log_device_debug(device, "device/sriov_numvfs sysfs attribute set to '%s'.", val);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sr_iov_section_verify(uint32_t num_vfs, SRIOV *sr_iov) {
|
||||||
|
assert(sr_iov);
|
||||||
|
|
||||||
|
if (section_is_invalid(sr_iov->section))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (sr_iov->vf == UINT32_MAX)
|
||||||
|
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
|
"%s: [SR-IOV] section without VirtualFunction= field configured. "
|
||||||
|
"Ignoring [SR-IOV] section from line %u.",
|
||||||
|
sr_iov->section->filename, sr_iov->section->line);
|
||||||
|
|
||||||
|
if (sr_iov->vf >= num_vfs)
|
||||||
|
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
|
"%s: VirtualFunction= must be smaller than the value specified in SR-IOVVirtualFunctions=. "
|
||||||
|
"Ignoring [SR-IOV] section from line %u.",
|
||||||
|
sr_iov->section->filename, sr_iov->section->line);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sr_iov_drop_invalid_sections(uint32_t num_vfs, OrderedHashmap *sr_iov_by_section) {
|
||||||
|
_cleanup_hashmap_free_ Hashmap *hashmap = NULL;
|
||||||
|
SRIOV *sr_iov;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
ORDERED_HASHMAP_FOREACH(sr_iov, sr_iov_by_section) {
|
||||||
|
SRIOV *dup;
|
||||||
|
|
||||||
|
if (sr_iov_section_verify(num_vfs, sr_iov) < 0) {
|
||||||
|
sr_iov_free(sr_iov);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(sr_iov->vf < INT_MAX);
|
||||||
|
|
||||||
|
dup = hashmap_remove(hashmap, UINT32_TO_PTR(sr_iov->vf + 1));
|
||||||
|
if (dup) {
|
||||||
|
log_warning("%s: Conflicting [SR-IOV] section is specified at line %u and %u, "
|
||||||
|
"dropping the [SR-IOV] section specified at line %u.",
|
||||||
|
dup->section->filename, sr_iov->section->line,
|
||||||
|
dup->section->line, dup->section->line);
|
||||||
|
sr_iov_free(dup);
|
||||||
|
}
|
||||||
|
|
||||||
|
r = hashmap_ensure_put(&hashmap, NULL, UINT32_TO_PTR(sr_iov->vf + 1), sr_iov);
|
||||||
|
if (r < 0)
|
||||||
|
return log_oom();
|
||||||
|
assert(r > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int config_parse_sr_iov_uint32(
|
||||||
|
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_(sr_iov_free_or_set_invalidp) SRIOV *sr_iov = NULL;
|
||||||
|
OrderedHashmap **sr_iov_by_section = data;
|
||||||
|
uint32_t k;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(filename);
|
||||||
|
assert(lvalue);
|
||||||
|
assert(rvalue);
|
||||||
|
assert(data);
|
||||||
|
|
||||||
|
r = sr_iov_new_static(sr_iov_by_section, filename, section_line, &sr_iov);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (isempty(rvalue)) {
|
||||||
|
if (streq(lvalue, "VirtualFunction"))
|
||||||
|
sr_iov->vf = UINT32_MAX;
|
||||||
|
else if (streq(lvalue, "VLANId"))
|
||||||
|
sr_iov->vlan = 0;
|
||||||
|
else if (streq(lvalue, "QualityOfService"))
|
||||||
|
sr_iov->qos = 0;
|
||||||
|
else
|
||||||
|
assert_not_reached();
|
||||||
|
|
||||||
|
TAKE_PTR(sr_iov);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = safe_atou32(rvalue, &k);
|
||||||
|
if (r < 0) {
|
||||||
|
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||||
|
"Failed to parse SR-IOV '%s=', ignoring assignment: %s", lvalue, rvalue);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (streq(lvalue, "VLANId")) {
|
||||||
|
if (k == 0 || k > 4095) {
|
||||||
|
log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid SR-IOV VLANId: %d", k);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
sr_iov->vlan = k;
|
||||||
|
} else if (streq(lvalue, "VirtualFunction")) {
|
||||||
|
if (k >= INT_MAX) {
|
||||||
|
log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid SR-IOV virtual function: %d", k);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
sr_iov->vf = k;
|
||||||
|
} else if (streq(lvalue, "QualityOfService"))
|
||||||
|
sr_iov->qos = k;
|
||||||
|
else
|
||||||
|
assert_not_reached();
|
||||||
|
|
||||||
|
TAKE_PTR(sr_iov);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int config_parse_sr_iov_vlan_proto(
|
||||||
|
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_(sr_iov_free_or_set_invalidp) SRIOV *sr_iov = NULL;
|
||||||
|
OrderedHashmap **sr_iov_by_section = data;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(filename);
|
||||||
|
assert(lvalue);
|
||||||
|
assert(rvalue);
|
||||||
|
assert(data);
|
||||||
|
|
||||||
|
r = sr_iov_new_static(sr_iov_by_section, filename, section_line, &sr_iov);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (isempty(rvalue) || streq(rvalue, "802.1Q"))
|
||||||
|
sr_iov->vlan_proto = ETH_P_8021Q;
|
||||||
|
else if (streq(rvalue, "802.1ad"))
|
||||||
|
sr_iov->vlan_proto = ETH_P_8021AD;
|
||||||
|
else {
|
||||||
|
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||||
|
"Invalid SR-IOV '%s=', ignoring assignment: %s", lvalue, rvalue);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TAKE_PTR(sr_iov);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int config_parse_sr_iov_link_state(
|
||||||
|
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_(sr_iov_free_or_set_invalidp) SRIOV *sr_iov = NULL;
|
||||||
|
OrderedHashmap **sr_iov_by_section = data;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(filename);
|
||||||
|
assert(lvalue);
|
||||||
|
assert(rvalue);
|
||||||
|
assert(data);
|
||||||
|
|
||||||
|
r = sr_iov_new_static(sr_iov_by_section, filename, section_line, &sr_iov);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
/* Unfortunately, SR_IOV_LINK_STATE_DISABLE is 2, not 0. So, we cannot use
|
||||||
|
* DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN() macro. */
|
||||||
|
|
||||||
|
if (isempty(rvalue)) {
|
||||||
|
sr_iov->link_state = _SR_IOV_LINK_STATE_INVALID;
|
||||||
|
TAKE_PTR(sr_iov);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (streq(rvalue, "auto")) {
|
||||||
|
sr_iov->link_state = SR_IOV_LINK_STATE_AUTO;
|
||||||
|
TAKE_PTR(sr_iov);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = parse_boolean(rvalue);
|
||||||
|
if (r < 0) {
|
||||||
|
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||||
|
"Failed to parse SR-IOV '%s=', ignoring assignment: %s", lvalue, rvalue);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sr_iov->link_state = r ? SR_IOV_LINK_STATE_ENABLE : SR_IOV_LINK_STATE_DISABLE;
|
||||||
|
TAKE_PTR(sr_iov);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int config_parse_sr_iov_boolean(
|
||||||
|
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_(sr_iov_free_or_set_invalidp) SRIOV *sr_iov = NULL;
|
||||||
|
OrderedHashmap **sr_iov_by_section = data;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(filename);
|
||||||
|
assert(lvalue);
|
||||||
|
assert(rvalue);
|
||||||
|
assert(data);
|
||||||
|
|
||||||
|
r = sr_iov_new_static(sr_iov_by_section, filename, section_line, &sr_iov);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (isempty(rvalue)) {
|
||||||
|
if (streq(lvalue, "MACSpoofCheck"))
|
||||||
|
sr_iov->vf_spoof_check_setting = -1;
|
||||||
|
else if (streq(lvalue, "QueryReceiveSideScaling"))
|
||||||
|
sr_iov->query_rss = -1;
|
||||||
|
else if (streq(lvalue, "Trust"))
|
||||||
|
sr_iov->trust = -1;
|
||||||
|
else
|
||||||
|
assert_not_reached();
|
||||||
|
|
||||||
|
TAKE_PTR(sr_iov);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = parse_boolean(rvalue);
|
||||||
|
if (r < 0) {
|
||||||
|
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse '%s=', ignoring: %s", lvalue, rvalue);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (streq(lvalue, "MACSpoofCheck"))
|
||||||
|
sr_iov->vf_spoof_check_setting = r;
|
||||||
|
else if (streq(lvalue, "QueryReceiveSideScaling"))
|
||||||
|
sr_iov->query_rss = r;
|
||||||
|
else if (streq(lvalue, "Trust"))
|
||||||
|
sr_iov->trust = r;
|
||||||
|
else
|
||||||
|
assert_not_reached();
|
||||||
|
|
||||||
|
TAKE_PTR(sr_iov);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int config_parse_sr_iov_mac(
|
||||||
|
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_(sr_iov_free_or_set_invalidp) SRIOV *sr_iov = NULL;
|
||||||
|
OrderedHashmap **sr_iov_by_section = data;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(filename);
|
||||||
|
assert(lvalue);
|
||||||
|
assert(rvalue);
|
||||||
|
assert(data);
|
||||||
|
|
||||||
|
r = sr_iov_new_static(sr_iov_by_section, filename, section_line, &sr_iov);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (isempty(rvalue)) {
|
||||||
|
sr_iov->mac = ETHER_ADDR_NULL;
|
||||||
|
TAKE_PTR(sr_iov);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = parse_ether_addr(rvalue, &sr_iov->mac);
|
||||||
|
if (r < 0) {
|
||||||
|
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||||
|
"Failed to parse SR-IOV '%s=', ignoring assignment: %s", lvalue, rvalue);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TAKE_PTR(sr_iov);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int config_parse_sr_iov_num_vfs(
|
||||||
|
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) {
|
||||||
|
|
||||||
|
uint32_t n, *num_vfs = data;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(filename);
|
||||||
|
assert(lvalue);
|
||||||
|
assert(rvalue);
|
||||||
|
assert(data);
|
||||||
|
|
||||||
|
if (isempty(rvalue)) {
|
||||||
|
*num_vfs = UINT32_MAX;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = safe_atou32(rvalue, &n);
|
||||||
|
if (r < 0) {
|
||||||
|
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||||
|
"Failed to parse %s=, ignoring assignment: %s", lvalue, rvalue);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n > INT_MAX) {
|
||||||
|
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||||
|
"The number of SR-IOV virtual functions is too large. It must be equal to "
|
||||||
|
"or smaller than 2147483647. Ignoring assignment: %"PRIu32, n);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*num_vfs = n;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
48
src/shared/netif-sriov.h
Normal file
48
src/shared/netif-sriov.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <linux/if_link.h>
|
||||||
|
|
||||||
|
#include "sd-device.h"
|
||||||
|
|
||||||
|
#include "conf-parser.h"
|
||||||
|
#include "ether-addr-util.h"
|
||||||
|
#include "hashmap.h"
|
||||||
|
|
||||||
|
typedef enum SRIOVLinkState {
|
||||||
|
SR_IOV_LINK_STATE_AUTO = IFLA_VF_LINK_STATE_AUTO,
|
||||||
|
SR_IOV_LINK_STATE_ENABLE = IFLA_VF_LINK_STATE_ENABLE,
|
||||||
|
SR_IOV_LINK_STATE_DISABLE = IFLA_VF_LINK_STATE_DISABLE,
|
||||||
|
_SR_IOV_LINK_STATE_MAX,
|
||||||
|
_SR_IOV_LINK_STATE_INVALID = -EINVAL,
|
||||||
|
} SRIOVLinkState;
|
||||||
|
|
||||||
|
typedef struct SRIOV {
|
||||||
|
ConfigSection *section;
|
||||||
|
OrderedHashmap *sr_iov_by_section;
|
||||||
|
|
||||||
|
uint32_t vf; /* 0 - 2147483646 */
|
||||||
|
uint32_t vlan; /* 0 - 4095, 0 disables VLAN filter */
|
||||||
|
uint32_t qos;
|
||||||
|
uint16_t vlan_proto; /* ETH_P_8021Q or ETH_P_8021AD */
|
||||||
|
int vf_spoof_check_setting;
|
||||||
|
int query_rss;
|
||||||
|
int trust;
|
||||||
|
SRIOVLinkState link_state;
|
||||||
|
struct ether_addr mac;
|
||||||
|
} SRIOV;
|
||||||
|
|
||||||
|
SRIOV *sr_iov_free(SRIOV *sr_iov);
|
||||||
|
int sr_iov_set_netlink_message(SRIOV *sr_iov, sd_netlink_message *req);
|
||||||
|
int sr_iov_get_num_vfs(sd_device *device, uint32_t *ret);
|
||||||
|
int sr_iov_set_num_vfs(sd_device *device, uint32_t num_vfs, OrderedHashmap *sr_iov_by_section);
|
||||||
|
int sr_iov_drop_invalid_sections(uint32_t num_vfs, OrderedHashmap *sr_iov_by_section);
|
||||||
|
|
||||||
|
DEFINE_SECTION_CLEANUP_FUNCTIONS(SRIOV, sr_iov_free);
|
||||||
|
|
||||||
|
CONFIG_PARSER_PROTOTYPE(config_parse_sr_iov_uint32);
|
||||||
|
CONFIG_PARSER_PROTOTYPE(config_parse_sr_iov_boolean);
|
||||||
|
CONFIG_PARSER_PROTOTYPE(config_parse_sr_iov_link_state);
|
||||||
|
CONFIG_PARSER_PROTOTYPE(config_parse_sr_iov_vlan_proto);
|
||||||
|
CONFIG_PARSER_PROTOTYPE(config_parse_sr_iov_mac);
|
||||||
|
CONFIG_PARSER_PROTOTYPE(config_parse_sr_iov_num_vfs);
|
||||||
@ -8,6 +8,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
|
|||||||
#include "ethtool-util.h"
|
#include "ethtool-util.h"
|
||||||
#include "link-config.h"
|
#include "link-config.h"
|
||||||
#include "net-condition.h"
|
#include "net-condition.h"
|
||||||
|
#include "netif-sriov.h"
|
||||||
#include "socket-util.h"
|
#include "socket-util.h"
|
||||||
%}
|
%}
|
||||||
struct ConfigPerfItem;
|
struct ConfigPerfItem;
|
||||||
@ -101,3 +102,13 @@ Link.RxMaxCoalescedHighFrames, config_parse_coalesce_u32,
|
|||||||
Link.TxCoalesceHighSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.tx_coalesce_usecs_high)
|
Link.TxCoalesceHighSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.tx_coalesce_usecs_high)
|
||||||
Link.TxMaxCoalescedHighFrames, config_parse_coalesce_u32, 0, offsetof(LinkConfig, coalesce.tx_max_coalesced_frames_high)
|
Link.TxMaxCoalescedHighFrames, config_parse_coalesce_u32, 0, offsetof(LinkConfig, coalesce.tx_max_coalesced_frames_high)
|
||||||
Link.CoalescePacketRateSampleIntervalSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.rate_sample_interval)
|
Link.CoalescePacketRateSampleIntervalSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.rate_sample_interval)
|
||||||
|
Link.SR-IOVVirtualFunctions, config_parse_sr_iov_num_vfs, 0, offsetof(LinkConfig, sr_iov_num_vfs)
|
||||||
|
SR-IOV.VirtualFunction, config_parse_sr_iov_uint32, 0, offsetof(LinkConfig, sr_iov_by_section)
|
||||||
|
SR-IOV.VLANId, config_parse_sr_iov_uint32, 0, offsetof(LinkConfig, sr_iov_by_section)
|
||||||
|
SR-IOV.QualityOfService, config_parse_sr_iov_uint32, 0, offsetof(LinkConfig, sr_iov_by_section)
|
||||||
|
SR-IOV.VLANProtocol, config_parse_sr_iov_vlan_proto, 0, offsetof(LinkConfig, sr_iov_by_section)
|
||||||
|
SR-IOV.MACSpoofCheck, config_parse_sr_iov_boolean, 0, offsetof(LinkConfig, sr_iov_by_section)
|
||||||
|
SR-IOV.QueryReceiveSideScaling, config_parse_sr_iov_boolean, 0, offsetof(LinkConfig, sr_iov_by_section)
|
||||||
|
SR-IOV.Trust, config_parse_sr_iov_boolean, 0, offsetof(LinkConfig, sr_iov_by_section)
|
||||||
|
SR-IOV.LinkState, config_parse_sr_iov_link_state, 0, offsetof(LinkConfig, sr_iov_by_section)
|
||||||
|
SR-IOV.MACAddress, config_parse_sr_iov_mac, 0, offsetof(LinkConfig, sr_iov_by_section)
|
||||||
|
|||||||
@ -22,6 +22,7 @@
|
|||||||
#include "log-link.h"
|
#include "log-link.h"
|
||||||
#include "memory-util.h"
|
#include "memory-util.h"
|
||||||
#include "net-condition.h"
|
#include "net-condition.h"
|
||||||
|
#include "netif-sriov.h"
|
||||||
#include "netif-util.h"
|
#include "netif-util.h"
|
||||||
#include "netlink-util.h"
|
#include "netlink-util.h"
|
||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
@ -60,6 +61,8 @@ static LinkConfig* link_config_free(LinkConfig *config) {
|
|||||||
free(config->wol_password_file);
|
free(config->wol_password_file);
|
||||||
erase_and_free(config->wol_password);
|
erase_and_free(config->wol_password);
|
||||||
|
|
||||||
|
ordered_hashmap_free_with_destructor(config->sr_iov_by_section, sr_iov_free);
|
||||||
|
|
||||||
return mfree(config);
|
return mfree(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,6 +250,7 @@ int link_load_one(LinkConfigContext *ctx, const char *filename) {
|
|||||||
.txqueuelen = UINT32_MAX,
|
.txqueuelen = UINT32_MAX,
|
||||||
.coalesce.use_adaptive_rx_coalesce = -1,
|
.coalesce.use_adaptive_rx_coalesce = -1,
|
||||||
.coalesce.use_adaptive_tx_coalesce = -1,
|
.coalesce.use_adaptive_tx_coalesce = -1,
|
||||||
|
.sr_iov_num_vfs = UINT32_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (i = 0; i < ELEMENTSOF(config->features); i++)
|
for (i = 0; i < ELEMENTSOF(config->features); i++)
|
||||||
@ -257,7 +261,9 @@ int link_load_one(LinkConfigContext *ctx, const char *filename) {
|
|||||||
STRV_MAKE_CONST(filename),
|
STRV_MAKE_CONST(filename),
|
||||||
(const char* const*) CONF_PATHS_STRV("systemd/network"),
|
(const char* const*) CONF_PATHS_STRV("systemd/network"),
|
||||||
dropin_dirname,
|
dropin_dirname,
|
||||||
"Match\0Link\0",
|
"Match\0"
|
||||||
|
"Link\0"
|
||||||
|
"SR-IOV\0",
|
||||||
config_item_perf_lookup, link_config_gperf_lookup,
|
config_item_perf_lookup, link_config_gperf_lookup,
|
||||||
CONFIG_PARSE_WARN, config, NULL);
|
CONFIG_PARSE_WARN, config, NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -285,6 +291,10 @@ int link_load_one(LinkConfigContext *ctx, const char *filename) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
r = sr_iov_drop_invalid_sections(config->sr_iov_num_vfs, config->sr_iov_by_section);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
log_debug("Parsed configuration file %s", filename);
|
log_debug("Parsed configuration file %s", filename);
|
||||||
|
|
||||||
LIST_PREPEND(configs, ctx->configs, TAKE_PTR(config));
|
LIST_PREPEND(configs, ctx->configs, TAKE_PTR(config));
|
||||||
@ -830,6 +840,77 @@ static int link_apply_alternative_names(Link *link, sd_netlink **rtnl) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sr_iov_configure(Link *link, sd_netlink **rtnl, SRIOV *sr_iov) {
|
||||||
|
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(link);
|
||||||
|
assert(rtnl);
|
||||||
|
assert(link->ifindex > 0);
|
||||||
|
|
||||||
|
if (!*rtnl) {
|
||||||
|
r = sd_netlink_open(rtnl);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sd_rtnl_message_new_link(*rtnl, &req, RTM_SETLINK, link->ifindex);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = sr_iov_set_netlink_message(sr_iov, req);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = sd_netlink_call(*rtnl, req, 0, NULL);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int link_apply_sr_iov_config(Link *link, sd_netlink **rtnl) {
|
||||||
|
SRIOV *sr_iov;
|
||||||
|
uint32_t n;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(link);
|
||||||
|
assert(link->config);
|
||||||
|
assert(link->device);
|
||||||
|
|
||||||
|
r = sr_iov_set_num_vfs(link->device, link->config->sr_iov_num_vfs, link->config->sr_iov_by_section);
|
||||||
|
if (r < 0)
|
||||||
|
log_link_warning_errno(link, r, "Failed to set the number of SR-IOV virtual functions, ignoring: %m");
|
||||||
|
|
||||||
|
if (ordered_hashmap_isempty(link->config->sr_iov_by_section))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
r = sr_iov_get_num_vfs(link->device, &n);
|
||||||
|
if (r < 0) {
|
||||||
|
log_link_warning_errno(link, r, "Failed to get the number of SR-IOV virtual functions, ignoring [SR-IOV] sections: %m");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (n == 0) {
|
||||||
|
log_link_warning(link, "No SR-IOV virtual function exists, ignoring [SR-IOV] sections: %m");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ORDERED_HASHMAP_FOREACH(sr_iov, link->config->sr_iov_by_section) {
|
||||||
|
if (sr_iov->vf >= n) {
|
||||||
|
log_link_warning(link, "SR-IOV virtual function %"PRIu32" does not exist, ignoring.", sr_iov->vf);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sr_iov_configure(link, rtnl, sr_iov);
|
||||||
|
if (r < 0)
|
||||||
|
log_link_warning_errno(link, r,
|
||||||
|
"Failed to configure SR-IOV virtual function %"PRIu32", ignoring: %m",
|
||||||
|
sr_iov->vf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int link_apply_config(LinkConfigContext *ctx, sd_netlink **rtnl, Link *link) {
|
int link_apply_config(LinkConfigContext *ctx, sd_netlink **rtnl, Link *link) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -861,6 +942,10 @@ int link_apply_config(LinkConfigContext *ctx, sd_netlink **rtnl, Link *link) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
r = link_apply_sr_iov_config(link, rtnl);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
#include "condition.h"
|
#include "condition.h"
|
||||||
#include "conf-parser.h"
|
#include "conf-parser.h"
|
||||||
#include "ethtool-util.h"
|
#include "ethtool-util.h"
|
||||||
|
#include "hashmap.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "net-condition.h"
|
#include "net-condition.h"
|
||||||
#include "netif-naming-scheme.h"
|
#include "netif-naming-scheme.h"
|
||||||
@ -76,6 +77,9 @@ struct LinkConfig {
|
|||||||
int autoneg_flow_control;
|
int autoneg_flow_control;
|
||||||
netdev_coalesce_param coalesce;
|
netdev_coalesce_param coalesce;
|
||||||
|
|
||||||
|
uint32_t sr_iov_num_vfs;
|
||||||
|
OrderedHashmap *sr_iov_by_section;
|
||||||
|
|
||||||
LIST_FIELDS(LinkConfig, configs);
|
LIST_FIELDS(LinkConfig, configs);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -80,3 +80,14 @@ RxMaxCoalescedHighFrames=
|
|||||||
TxCoalesceHighSec=
|
TxCoalesceHighSec=
|
||||||
TxMaxCoalescedHighFrames=
|
TxMaxCoalescedHighFrames=
|
||||||
CoalescePacketRateSampleIntervalSec=
|
CoalescePacketRateSampleIntervalSec=
|
||||||
|
SR-IOVVirtualFunctions=
|
||||||
|
[SR-IOV]
|
||||||
|
VirtualFunction=
|
||||||
|
MACSpoofCheck=
|
||||||
|
VLANId=
|
||||||
|
VLANProtocol=
|
||||||
|
QualityOfService=
|
||||||
|
QueryReceiveSideScaling=
|
||||||
|
Trust=
|
||||||
|
LinkState=
|
||||||
|
MACAddress=
|
||||||
|
|||||||
7
test/test-network/conf/25-sriov-udev.network
Normal file
7
test/test-network/conf/25-sriov-udev.network
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
[Match]
|
||||||
|
Name=eni99np1
|
||||||
|
|
||||||
|
[Network]
|
||||||
|
Address=192.168.100.100/24
|
||||||
|
IPv6AcceptRA=no
|
||||||
40
test/test-network/conf/25-sriov.link
Normal file
40
test/test-network/conf/25-sriov.link
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
[Match]
|
||||||
|
Driver=netdevsim
|
||||||
|
|
||||||
|
[Link]
|
||||||
|
NamePolicy=keep kernel database onboard slot path
|
||||||
|
AlternativeNamesPolicy=database onboard slot path mac
|
||||||
|
MACAddressPolicy=persistent
|
||||||
|
|
||||||
|
[SR-IOV]
|
||||||
|
VirtualFunction=0
|
||||||
|
VLANId=5
|
||||||
|
VLANProtocol=802.1ad
|
||||||
|
QualityOfService=1
|
||||||
|
MACSpoofCheck=yes
|
||||||
|
QueryReceiveSideScaling=yes
|
||||||
|
Trust=yes
|
||||||
|
LinkState=yes
|
||||||
|
MACAddress=00:11:22:33:44:55
|
||||||
|
|
||||||
|
[SR-IOV]
|
||||||
|
VirtualFunction=1
|
||||||
|
VLANId=6
|
||||||
|
VLANProtocol=802.1Q
|
||||||
|
QualityOfService=2
|
||||||
|
MACSpoofCheck=no
|
||||||
|
QueryReceiveSideScaling=no
|
||||||
|
Trust=no
|
||||||
|
LinkState=no
|
||||||
|
MACAddress=00:11:22:33:44:56
|
||||||
|
|
||||||
|
[SR-IOV]
|
||||||
|
VirtualFunction=2
|
||||||
|
VLANId=7
|
||||||
|
QualityOfService=3
|
||||||
|
MACSpoofCheck=no
|
||||||
|
QueryReceiveSideScaling=no
|
||||||
|
Trust=no
|
||||||
|
LinkState=auto
|
||||||
|
MACAddress=00:11:22:33:44:57
|
||||||
@ -176,7 +176,7 @@ def expectedFailureIfAlternativeNameIsNotAvailable():
|
|||||||
call('ip link add dummy98 type dummy', stderr=subprocess.DEVNULL)
|
call('ip link add dummy98 type dummy', stderr=subprocess.DEVNULL)
|
||||||
rc = call('ip link prop add dev dummy98 altname hogehogehogehogehoge', stderr=subprocess.DEVNULL)
|
rc = call('ip link prop add dev dummy98 altname hogehogehogehogehoge', stderr=subprocess.DEVNULL)
|
||||||
if rc == 0:
|
if rc == 0:
|
||||||
rc = call('ip link show dev hogehogehogehogehoge', stderr=subprocess.DEVNULL)
|
rc = call('ip link show dev hogehogehogehogehoge', stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||||
if rc == 0:
|
if rc == 0:
|
||||||
supported = True
|
supported = True
|
||||||
|
|
||||||
@ -2065,7 +2065,6 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
|
|||||||
'25-route-vrf.network',
|
'25-route-vrf.network',
|
||||||
'25-gateway-static.network',
|
'25-gateway-static.network',
|
||||||
'25-gateway-next-static.network',
|
'25-gateway-next-static.network',
|
||||||
'25-sriov.network',
|
|
||||||
'25-sysctl-disable-ipv6.network',
|
'25-sysctl-disable-ipv6.network',
|
||||||
'25-sysctl.network',
|
'25-sysctl.network',
|
||||||
'25-test1.network',
|
'25-test1.network',
|
||||||
@ -3450,32 +3449,6 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
|
|||||||
self.assertRegex(output, 'qdisc fq_pie 3a: root')
|
self.assertRegex(output, 'qdisc fq_pie 3a: root')
|
||||||
self.assertRegex(output, 'limit 200000p')
|
self.assertRegex(output, 'limit 200000p')
|
||||||
|
|
||||||
@expectedFailureIfNetdevsimWithSRIOVIsNotAvailable()
|
|
||||||
def test_sriov(self):
|
|
||||||
call('rmmod netdevsim', stderr=subprocess.DEVNULL)
|
|
||||||
call('modprobe netdevsim', stderr=subprocess.DEVNULL)
|
|
||||||
with open('/sys/bus/netdevsim/new_device', mode='w') as f:
|
|
||||||
f.write('99 1')
|
|
||||||
|
|
||||||
call('udevadm settle')
|
|
||||||
call('udevadm info -w10s /sys/devices/netdevsim99/net/eni99np1', stderr=subprocess.DEVNULL)
|
|
||||||
with open('/sys/class/net/eni99np1/device/sriov_numvfs', mode='w') as f:
|
|
||||||
f.write('3')
|
|
||||||
|
|
||||||
copy_unit_to_networkd_unit_path('25-sriov.network')
|
|
||||||
start_networkd()
|
|
||||||
self.wait_online(['eni99np1:routable'])
|
|
||||||
|
|
||||||
output = check_output('ip link show dev eni99np1')
|
|
||||||
print(output)
|
|
||||||
self.assertRegex(output,
|
|
||||||
'vf 0 .*00:11:22:33:44:55.*vlan 5, qos 1, vlan protocol 802.1ad, spoof checking on, link-state enable, trust on, query_rss on\n *'
|
|
||||||
'vf 1 .*00:11:22:33:44:56.*vlan 6, qos 2, spoof checking off, link-state disable, trust off, query_rss off\n *'
|
|
||||||
'vf 2 .*00:11:22:33:44:57.*vlan 7, qos 3, spoof checking off, link-state auto, trust off, query_rss off'
|
|
||||||
)
|
|
||||||
|
|
||||||
call('rmmod netdevsim', stderr=subprocess.DEVNULL)
|
|
||||||
|
|
||||||
def test_wait_online_ipv4(self):
|
def test_wait_online_ipv4(self):
|
||||||
copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-with-ipv6-prefix.network', 'dhcp-client-ipv4-ipv6ra-prefix-client-with-delay.network')
|
copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-with-ipv6-prefix.network', 'dhcp-client-ipv4-ipv6ra-prefix-client-with-delay.network')
|
||||||
start_networkd()
|
start_networkd()
|
||||||
@ -3999,6 +3972,133 @@ class NetworkdBridgeTests(unittest.TestCase, Utilities):
|
|||||||
print(output)
|
print(output)
|
||||||
self.assertIn('from all to 8.8.8.8 lookup 100', output)
|
self.assertIn('from all to 8.8.8.8 lookup 100', output)
|
||||||
|
|
||||||
|
class NetworkdSRIOVTests(unittest.TestCase, Utilities):
|
||||||
|
units = [
|
||||||
|
'25-sriov-udev.network',
|
||||||
|
'25-sriov.link',
|
||||||
|
'25-sriov.network',
|
||||||
|
]
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
stop_networkd(show_logs=False)
|
||||||
|
call('rmmod netdevsim', stderr=subprocess.DEVNULL)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
remove_unit_from_networkd_path(self.units)
|
||||||
|
stop_networkd(show_logs=True)
|
||||||
|
call('rmmod netdevsim', stderr=subprocess.DEVNULL)
|
||||||
|
|
||||||
|
@expectedFailureIfNetdevsimWithSRIOVIsNotAvailable()
|
||||||
|
def test_sriov(self):
|
||||||
|
call('modprobe netdevsim', stderr=subprocess.DEVNULL)
|
||||||
|
|
||||||
|
with open('/sys/bus/netdevsim/new_device', mode='w') as f:
|
||||||
|
f.write('99 1')
|
||||||
|
|
||||||
|
call('udevadm settle')
|
||||||
|
call('udevadm info -w10s /sys/devices/netdevsim99/net/eni99np1', stderr=subprocess.DEVNULL)
|
||||||
|
with open('/sys/class/net/eni99np1/device/sriov_numvfs', mode='w') as f:
|
||||||
|
f.write('3')
|
||||||
|
|
||||||
|
copy_unit_to_networkd_unit_path('25-sriov.network')
|
||||||
|
start_networkd()
|
||||||
|
self.wait_online(['eni99np1:routable'])
|
||||||
|
|
||||||
|
output = check_output('ip link show dev eni99np1')
|
||||||
|
print(output)
|
||||||
|
self.assertRegex(output,
|
||||||
|
'vf 0 .*00:11:22:33:44:55.*vlan 5, qos 1, vlan protocol 802.1ad, spoof checking on, link-state enable, trust on, query_rss on\n *'
|
||||||
|
'vf 1 .*00:11:22:33:44:56.*vlan 6, qos 2, spoof checking off, link-state disable, trust off, query_rss off\n *'
|
||||||
|
'vf 2 .*00:11:22:33:44:57.*vlan 7, qos 3, spoof checking off, link-state auto, trust off, query_rss off'
|
||||||
|
)
|
||||||
|
|
||||||
|
@expectedFailureIfNetdevsimWithSRIOVIsNotAvailable()
|
||||||
|
def test_sriov_udev(self):
|
||||||
|
call('modprobe netdevsim', stderr=subprocess.DEVNULL)
|
||||||
|
|
||||||
|
copy_unit_to_networkd_unit_path('25-sriov.link', '25-sriov-udev.network')
|
||||||
|
call('udevadm control --reload')
|
||||||
|
|
||||||
|
with open('/sys/bus/netdevsim/new_device', mode='w') as f:
|
||||||
|
f.write('99 1')
|
||||||
|
|
||||||
|
start_networkd()
|
||||||
|
self.wait_online(['eni99np1:routable'])
|
||||||
|
|
||||||
|
output = check_output('ip link show dev eni99np1')
|
||||||
|
print(output)
|
||||||
|
self.assertRegex(output,
|
||||||
|
'vf 0 .*00:11:22:33:44:55.*vlan 5, qos 1, vlan protocol 802.1ad, spoof checking on, link-state enable, trust on, query_rss on\n *'
|
||||||
|
'vf 1 .*00:11:22:33:44:56.*vlan 6, qos 2, spoof checking off, link-state disable, trust off, query_rss off\n *'
|
||||||
|
'vf 2 .*00:11:22:33:44:57.*vlan 7, qos 3, spoof checking off, link-state auto, trust off, query_rss off'
|
||||||
|
)
|
||||||
|
self.assertNotIn('vf 3', output)
|
||||||
|
self.assertNotIn('vf 4', output)
|
||||||
|
|
||||||
|
with open(os.path.join(network_unit_file_path, '25-sriov.link'), mode='a') as f:
|
||||||
|
f.write('[Link]\nSR-IOVVirtualFunctions=4\n')
|
||||||
|
|
||||||
|
call('udevadm control --reload')
|
||||||
|
call('udevadm trigger --action add --settle /sys/devices/netdevsim99/net/eni99np1')
|
||||||
|
|
||||||
|
output = check_output('ip link show dev eni99np1')
|
||||||
|
print(output)
|
||||||
|
self.assertRegex(output,
|
||||||
|
'vf 0 .*00:11:22:33:44:55.*vlan 5, qos 1, vlan protocol 802.1ad, spoof checking on, link-state enable, trust on, query_rss on\n *'
|
||||||
|
'vf 1 .*00:11:22:33:44:56.*vlan 6, qos 2, spoof checking off, link-state disable, trust off, query_rss off\n *'
|
||||||
|
'vf 2 .*00:11:22:33:44:57.*vlan 7, qos 3, spoof checking off, link-state auto, trust off, query_rss off\n *'
|
||||||
|
'vf 3'
|
||||||
|
)
|
||||||
|
self.assertNotIn('vf 4', output)
|
||||||
|
|
||||||
|
with open(os.path.join(network_unit_file_path, '25-sriov.link'), mode='a') as f:
|
||||||
|
f.write('[Link]\nSR-IOVVirtualFunctions=\n')
|
||||||
|
|
||||||
|
call('udevadm control --reload')
|
||||||
|
call('udevadm trigger --action add --settle /sys/devices/netdevsim99/net/eni99np1')
|
||||||
|
|
||||||
|
output = check_output('ip link show dev eni99np1')
|
||||||
|
print(output)
|
||||||
|
self.assertRegex(output,
|
||||||
|
'vf 0 .*00:11:22:33:44:55.*vlan 5, qos 1, vlan protocol 802.1ad, spoof checking on, link-state enable, trust on, query_rss on\n *'
|
||||||
|
'vf 1 .*00:11:22:33:44:56.*vlan 6, qos 2, spoof checking off, link-state disable, trust off, query_rss off\n *'
|
||||||
|
'vf 2 .*00:11:22:33:44:57.*vlan 7, qos 3, spoof checking off, link-state auto, trust off, query_rss off\n *'
|
||||||
|
'vf 3'
|
||||||
|
)
|
||||||
|
self.assertNotIn('vf 4', output)
|
||||||
|
|
||||||
|
with open(os.path.join(network_unit_file_path, '25-sriov.link'), mode='a') as f:
|
||||||
|
f.write('[Link]\nSR-IOVVirtualFunctions=2\n')
|
||||||
|
|
||||||
|
call('udevadm control --reload')
|
||||||
|
call('udevadm trigger --action add --settle /sys/devices/netdevsim99/net/eni99np1')
|
||||||
|
|
||||||
|
output = check_output('ip link show dev eni99np1')
|
||||||
|
print(output)
|
||||||
|
self.assertRegex(output,
|
||||||
|
'vf 0 .*00:11:22:33:44:55.*vlan 5, qos 1, vlan protocol 802.1ad, spoof checking on, link-state enable, trust on, query_rss on\n *'
|
||||||
|
'vf 1 .*00:11:22:33:44:56.*vlan 6, qos 2, spoof checking off, link-state disable, trust off, query_rss off'
|
||||||
|
)
|
||||||
|
self.assertNotIn('vf 2', output)
|
||||||
|
self.assertNotIn('vf 3', output)
|
||||||
|
self.assertNotIn('vf 4', output)
|
||||||
|
|
||||||
|
with open(os.path.join(network_unit_file_path, '25-sriov.link'), mode='a') as f:
|
||||||
|
f.write('[Link]\nSR-IOVVirtualFunctions=\n')
|
||||||
|
|
||||||
|
call('udevadm control --reload')
|
||||||
|
call('udevadm trigger --action add --settle /sys/devices/netdevsim99/net/eni99np1')
|
||||||
|
|
||||||
|
output = check_output('ip link show dev eni99np1')
|
||||||
|
print(output)
|
||||||
|
self.assertRegex(output,
|
||||||
|
'vf 0 .*00:11:22:33:44:55.*vlan 5, qos 1, vlan protocol 802.1ad, spoof checking on, link-state enable, trust on, query_rss on\n *'
|
||||||
|
'vf 1 .*00:11:22:33:44:56.*vlan 6, qos 2, spoof checking off, link-state disable, trust off, query_rss off\n *'
|
||||||
|
'vf 2 .*00:11:22:33:44:57.*vlan 7, qos 3, spoof checking off, link-state auto, trust off, query_rss off'
|
||||||
|
)
|
||||||
|
self.assertNotIn('vf 3', output)
|
||||||
|
self.assertNotIn('vf 4', output)
|
||||||
|
|
||||||
class NetworkdLLDPTests(unittest.TestCase, Utilities):
|
class NetworkdLLDPTests(unittest.TestCase, Utilities):
|
||||||
links = ['veth99']
|
links = ['veth99']
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user