summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2023-03-03 11:52:24 +0100
committerBeniamino Galvani <bgalvani@redhat.com>2023-03-03 11:52:24 +0100
commit992e39e048f28cd83004ec5232f009c3cd16d292 (patch)
treef261cc8f0b2929d0d9e3e488499d12f8f3b04af5
parent86b922695f18566132980bd23516038b6ca4c0f4 (diff)
parent220189b9e67199f75d55d648a5d86bfaa07d79ae (diff)
merge: branch 'bg/link-setting'
https://bugzilla.redhat.com/show_bug.cgi?id=2158328 https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1541
-rw-r--r--Makefile.am2
-rw-r--r--docs/libnm/libnm-docs.xml1
-rw-r--r--src/core/devices/nm-device-private.h2
-rw-r--r--src/core/devices/nm-device.c163
-rw-r--r--src/core/devices/ovs/nm-device-ovs-interface.c4
-rw-r--r--src/core/platform/tests/test-link.c31
-rw-r--r--src/libnm-client-impl/libnm.ver6
-rw-r--r--src/libnm-client-public/NetworkManager.h1
-rw-r--r--src/libnm-client-public/nm-autoptr.h1
-rw-r--r--src/libnm-core-impl/gen-metadata-nm-settings-libnm-core.xml.in20
-rw-r--r--src/libnm-core-impl/meson.build1
-rw-r--r--src/libnm-core-impl/nm-meta-setting-base-impl.c9
-rw-r--r--src/libnm-core-impl/nm-setting-link.c241
-rw-r--r--src/libnm-core-impl/tests/test-setting.c2
-rw-r--r--src/libnm-core-intern/nm-core-internal.h1
-rw-r--r--src/libnm-core-intern/nm-meta-setting-base-impl.h1
-rw-r--r--src/libnm-core-public/meson.build1
-rw-r--r--src/libnm-core-public/nm-core-types.h1
-rw-r--r--src/libnm-core-public/nm-setting-link.h52
-rw-r--r--src/libnm-platform/nm-linux-platform.c50
-rw-r--r--src/libnm-platform/nm-platform.c57
-rw-r--r--src/libnm-platform/nm-platform.h43
-rw-r--r--src/libnmc-setting/nm-meta-setting-base-impl.c9
-rw-r--r--src/libnmc-setting/nm-meta-setting-base-impl.h1
-rw-r--r--src/libnmc-setting/nm-meta-setting-desc.c61
-rw-r--r--src/libnmc-setting/settings-docs.h.in4
-rw-r--r--src/nmcli/connections.c6
-rw-r--r--src/nmcli/gen-metadata-nm-settings-nmcli.xml.in10
-rw-r--r--vapi/NM-1.0.metadata1
29 files changed, 761 insertions, 21 deletions
diff --git a/Makefile.am b/Makefile.am
index 9109af4c6a..6fc3d035b6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1265,6 +1265,7 @@ src_libnm_core_impl_lib_h_pub_real = \
src/libnm-core-public/nm-setting-ip-tunnel.h \
src/libnm-core-public/nm-setting-ip4-config.h \
src/libnm-core-public/nm-setting-ip6-config.h \
+ src/libnm-core-public/nm-setting-link.h \
src/libnm-core-public/nm-setting-loopback.h \
src/libnm-core-public/nm-setting-macsec.h \
src/libnm-core-public/nm-setting-macvlan.h \
@@ -1346,6 +1347,7 @@ src_libnm_core_impl_lib_c_settings_real = \
src/libnm-core-impl/nm-setting-ip-tunnel.c \
src/libnm-core-impl/nm-setting-ip4-config.c \
src/libnm-core-impl/nm-setting-ip6-config.c \
+ src/libnm-core-impl/nm-setting-link.c \
src/libnm-core-impl/nm-setting-loopback.c \
src/libnm-core-impl/nm-setting-macsec.c \
src/libnm-core-impl/nm-setting-macvlan.c \
diff --git a/docs/libnm/libnm-docs.xml b/docs/libnm/libnm-docs.xml
index df668e4ee9..09468a5cdb 100644
--- a/docs/libnm/libnm-docs.xml
+++ b/docs/libnm/libnm-docs.xml
@@ -332,6 +332,7 @@ print ("NetworkManager version " + client.get_version())]]></programlisting></in
<xi:include href="xml/nm-setting-ip-tunnel.xml"/>
<xi:include href="xml/nm-setting-ip4-config.xml"/>
<xi:include href="xml/nm-setting-ip6-config.xml"/>
+ <xi:include href="xml/nm-setting-link.xml"/>
<xi:include href="xml/nm-setting-loopback.xml"/>
<xi:include href="xml/nm-setting-macsec.xml"/>
<xi:include href="xml/nm-setting-macvlan.xml"/>
diff --git a/src/core/devices/nm-device-private.h b/src/core/devices/nm-device-private.h
index 6f3a1c3e42..013bc7fd86 100644
--- a/src/core/devices/nm-device-private.h
+++ b/src/core/devices/nm-device-private.h
@@ -176,4 +176,6 @@ void nm_device_auth_request(NMDevice *self,
NMManagerDeviceAuthRequestFunc callback,
gpointer user_data);
+void nm_device_link_properties_set(NMDevice *self, gboolean reapply);
+
#endif /* NM_DEVICE_PRIVATE_H */
diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c
index c0cdd733d9..300c958743 100644
--- a/src/core/devices/nm-device.c
+++ b/src/core/devices/nm-device.c
@@ -599,6 +599,8 @@ typedef struct _NMDevicePrivate {
bool tc_committed : 1;
+ bool link_props_set : 1;
+
NMDeviceStageState stage1_sriov_state : 3;
char *current_stable_id;
@@ -702,6 +704,10 @@ typedef struct _NMDevicePrivate {
GHashTable *ip6_saved_properties;
EthtoolState *ethtool_state;
+ struct {
+ NMPlatformLinkProps props;
+ NMPlatformLinkChangeFlags flags;
+ } link_props_state;
/* master interface for bridge/bond/team slave */
NMDevice *master;
@@ -2750,6 +2756,151 @@ _ethtool_state_set(NMDevice *self)
priv->ethtool_state = g_steal_pointer(&ethtool_state);
}
+static NMPlatformLinkChangeFlags
+link_properties_fill_from_setting(NMDevice *self, NMPlatformLinkProps *props)
+{
+ NMPlatformLinkChangeFlags flags = NM_PLATFORM_LINK_CHANGE_NONE;
+ NMSettingLink *s_link;
+ gint64 v;
+
+ *props = (NMPlatformLinkProps){};
+
+ s_link = nm_device_get_applied_setting(self, NM_TYPE_SETTING_LINK);
+ if (!s_link)
+ return 0;
+
+ v = nm_setting_link_get_tx_queue_length(s_link);
+ if (v != -1) {
+ props->tx_queue_length = (guint32) v;
+ flags |= NM_PLATFORM_LINK_CHANGE_TX_QUEUE_LENGTH;
+ }
+
+ v = nm_setting_link_get_gso_max_size(s_link);
+ if (v != -1) {
+ props->gso_max_size = (guint32) v;
+ flags |= NM_PLATFORM_LINK_CHANGE_GSO_MAX_SIZE;
+ }
+
+ v = nm_setting_link_get_gso_max_segments(s_link);
+ if (v != -1) {
+ props->gso_max_segments = (guint32) v;
+ flags |= NM_PLATFORM_LINK_CHANGE_GSO_MAX_SEGMENTS;
+ }
+
+ v = nm_setting_link_get_gro_max_size(s_link);
+ if (v != -1) {
+ props->gro_max_size = (guint32) v;
+ flags |= NM_PLATFORM_LINK_CHANGE_GRO_MAX_SIZE;
+ }
+
+ return flags;
+}
+
+void
+nm_device_link_properties_set(NMDevice *self, gboolean reapply)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ NMPlatformLinkProps props;
+ NMPlatformLinkChangeFlags flags;
+ NMPlatform *platform;
+ const NMPlatformLink *plink;
+ int ifindex;
+
+ ifindex = nm_device_get_ip_ifindex(self);
+ if (ifindex <= 0)
+ return;
+
+ if (priv->link_props_set && !reapply)
+ return;
+
+ priv->link_props_set = TRUE;
+
+ flags = link_properties_fill_from_setting(self, &props);
+
+ if (flags == NM_PLATFORM_LINK_CHANGE_NONE
+ && priv->link_props_state.flags == NM_PLATFORM_LINK_CHANGE_NONE) {
+ /* Nothing to set now, and nothing was set previously. */
+ return;
+ }
+
+ platform = nm_device_get_platform(self);
+
+ if (priv->link_props_state.flags == NM_PLATFORM_LINK_CHANGE_NONE) {
+ /* It's the first time we reach here. Try to fetch the current
+ * link settings (reset them later). */
+ plink = nm_platform_link_get(platform, ifindex);
+ if (plink) {
+ priv->link_props_state.props = plink->link_props;
+ priv->link_props_state.flags = flags;
+ } else {
+ /* Unknown properties. The "priv->link_props_state.flags" stays unset.
+ * It indicates that "priv->link_props_state.props" is unknown. */
+ }
+
+ } else {
+ /* From a previous call we have some "priv->link_props_state.flags"
+ * flags, which indicates that all link props are cached. Also add
+ * "flags" which are are going to set, to indicate that those flags
+ * will need to be reset later. */
+ priv->link_props_state.flags |= flags;
+ }
+
+#define _RESET(_f, _field) \
+ if (!NM_FLAGS_HAS(flags, (_f)) && NM_FLAGS_HAS(priv->link_props_state.flags, (_f))) { \
+ props._field = priv->link_props_state.props._field; \
+ priv->link_props_state.flags &= ~(_f); \
+ flags |= (_f); \
+ }
+
+ /* During reapply, if we previously set some "priv->link_props_state.flags"
+ * but now not anymore (according to "flags"), then we reset the value now.
+ *
+ * We do this by copying the props field from "priv->link_props_state" to
+ * "props", reset the flag in "priv->link_props_state.flags" and set the
+ * flag in "flags" (for changing it). */
+ _RESET(NM_PLATFORM_LINK_CHANGE_TX_QUEUE_LENGTH, tx_queue_length);
+ _RESET(NM_PLATFORM_LINK_CHANGE_GSO_MAX_SIZE, gso_max_size);
+ _RESET(NM_PLATFORM_LINK_CHANGE_GSO_MAX_SEGMENTS, gso_max_segments);
+ _RESET(NM_PLATFORM_LINK_CHANGE_GRO_MAX_SIZE, gro_max_size);
+
+ if (nm_platform_link_change(platform, ifindex, &props, flags)) {
+ _LOGD(LOGD_DEVICE, "link properties successfully set");
+ } else {
+ _LOGW(LOGD_DEVICE, "failure setting link properties");
+ }
+}
+
+static void
+link_properties_reset(NMDevice *self)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ NMPlatform *platform;
+ int ifindex;
+
+ if (priv->link_props_state.flags == 0)
+ goto out;
+
+ ifindex = nm_device_get_ip_ifindex(self);
+ if (ifindex <= 0)
+ goto out;
+
+ platform = nm_device_get_platform(self);
+ nm_assert(platform);
+
+ if (nm_platform_link_change(platform,
+ ifindex,
+ &priv->link_props_state.props,
+ priv->link_props_state.flags)) {
+ _LOGD(LOGD_DEVICE, "link properties successfully reset");
+ } else {
+ _LOGW(LOGD_DEVICE, "failure resetting link properties");
+ }
+
+out:
+ priv->link_props_set = FALSE;
+ priv->link_props_state.flags = 0;
+}
+
/*****************************************************************************/
gboolean
@@ -9760,10 +9911,12 @@ activate_stage2_device_config(NMDevice *self)
nm_device_state_changed(self, NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_REASON_NONE);
- if (!nm_device_sys_iface_state_is_external_or_assume(self))
+ if (!nm_device_sys_iface_state_is_external(self)) {
_ethtool_state_set(self);
+ nm_device_link_properties_set(self, FALSE);
+ }
- if (!nm_device_sys_iface_state_is_external_or_assume(self)) {
+ if (!nm_device_sys_iface_state_is_external(self)) {
if (!priv->tc_committed && !tc_commit(self)) {
_LOGW(LOGD_DEVICE, "failed applying traffic control rules");
nm_device_state_changed(self,
@@ -12828,7 +12981,8 @@ can_reapply_change(NMDevice *self,
NM_SETTING_USER_SETTING_NAME,
NM_SETTING_PROXY_SETTING_NAME,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
- NM_SETTING_IP6_CONFIG_SETTING_NAME))
+ NM_SETTING_IP6_CONFIG_SETTING_NAME,
+ NM_SETTING_LINK_SETTING_NAME))
return TRUE;
if (nm_streq(setting_name, NM_SETTING_WIRED_SETTING_NAME)) {
@@ -13024,6 +13178,8 @@ check_and_reapply_connection(NMDevice *self,
*************************************************************************/
klass->reapply_connection(self, con_old, con_new);
+ nm_device_link_properties_set(self, TRUE);
+
if (priv->state >= NM_DEVICE_STATE_CONFIG)
lldp_setup(self, NM_TERNARY_DEFAULT);
@@ -15622,6 +15778,7 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu
}
_ethtool_state_reset(self);
+ link_properties_reset(self);
if (priv->promisc_reset != NM_OPTION_BOOL_DEFAULT && ifindex > 0) {
nm_platform_link_change_flags(nm_device_get_platform(self),
diff --git a/src/core/devices/ovs/nm-device-ovs-interface.c b/src/core/devices/ovs/nm-device-ovs-interface.c
index 711f65cb5b..3ff52c4645 100644
--- a/src/core/devices/ovs/nm-device-ovs-interface.c
+++ b/src/core/devices/ovs/nm-device-ovs-interface.c
@@ -132,6 +132,8 @@ link_changed(NMDevice *device, const NMPlatformLink *pllink)
nm_device_devip_set_failed(device, AF_INET6, NM_DEVICE_STATE_REASON_CONFIG_FAILED);
return;
}
+
+ nm_device_link_properties_set(device, FALSE);
nm_device_bring_up(device);
nm_device_devip_set_state(device, AF_INET, NM_DEVICE_IP_STATE_PENDING, NULL);
@@ -214,6 +216,7 @@ _set_ip_ifindex_tun(gpointer user_data)
priv->wait_link_is_waiting = FALSE;
nm_device_set_ip_ifindex(device, priv->wait_link_ifindex);
+ nm_device_link_properties_set(device, FALSE);
nm_device_devip_set_state(device, AF_INET, NM_DEVICE_IP_STATE_PENDING, NULL);
nm_device_devip_set_state(device, AF_INET6, NM_DEVICE_IP_STATE_PENDING, NULL);
@@ -303,6 +306,7 @@ act_stage3_ip_config(NMDevice *device, int addr_family)
return;
}
+ nm_device_link_properties_set(device, FALSE);
nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, NULL);
}
diff --git a/src/core/platform/tests/test-link.c b/src/core/platform/tests/test-link.c
index fd341b4c8b..eb351eaa7d 100644
--- a/src/core/platform/tests/test-link.c
+++ b/src/core/platform/tests/test-link.c
@@ -2583,6 +2583,35 @@ test_vlan_set_xgress(void)
/*****************************************************************************/
static void
+test_link_set_properties(void)
+{
+ const NMPlatformLink *link;
+ NMPlatformLinkProps props;
+ NMPlatformLinkChangeFlags flags;
+
+ props = (NMPlatformLinkProps){
+ .tx_queue_length = 599,
+ .gso_max_size = 10001,
+ .gso_max_segments = 512,
+ };
+ flags = NM_PLATFORM_LINK_CHANGE_TX_QUEUE_LENGTH | NM_PLATFORM_LINK_CHANGE_GSO_MAX_SIZE
+ | NM_PLATFORM_LINK_CHANGE_GSO_MAX_SEGMENTS;
+
+ link = nmtstp_link_dummy_add(NM_PLATFORM_GET, FALSE, "dummy1");
+ g_assert(nm_platform_link_change(NM_PLATFORM_GET, link->ifindex, &props, flags));
+
+ link = nmtstp_link_get(NM_PLATFORM_GET, link->ifindex, "dummy1");
+ g_assert(link);
+ g_assert_cmpint(link->link_props.tx_queue_length, ==, 599);
+ g_assert_cmpint(link->link_props.gso_max_size, ==, 10001);
+ g_assert_cmpint(link->link_props.gso_max_segments, ==, 512);
+
+ nmtstp_link_delete(NULL, -1, link->ifindex, "dummy1", TRUE);
+}
+
+/*****************************************************************************/
+
+static void
test_create_many_links_do(guint n_devices)
{
gint64 time, start_time = nm_utils_get_monotonic_timestamp_nsec();
@@ -3948,6 +3977,8 @@ _nmtstp_setup_tests(void)
g_test_add_func("/link/software/vlan/set-xgress", test_vlan_set_xgress);
+ g_test_add_func("/link/set-properties", test_link_set_properties);
+
g_test_add_data_func("/link/create-many-links/20",
GUINT_TO_POINTER(20),
test_create_many_links);
diff --git a/src/libnm-client-impl/libnm.ver b/src/libnm-client-impl/libnm.ver
index fbaebb13ec..5a89536ab3 100644
--- a/src/libnm-client-impl/libnm.ver
+++ b/src/libnm-client-impl/libnm.ver
@@ -1930,4 +1930,10 @@ libnm_1_44_0 {
global:
nm_setting_gsm_get_initial_eps_apn;
nm_setting_gsm_get_initial_eps_config;
+ nm_setting_link_get_gro_max_size;
+ nm_setting_link_get_gso_max_segments;
+ nm_setting_link_get_gso_max_size;
+ nm_setting_link_get_tx_queue_length;
+ nm_setting_link_get_type;
+ nm_setting_link_new;
} libnm_1_42_0;
diff --git a/src/libnm-client-public/NetworkManager.h b/src/libnm-client-public/NetworkManager.h
index da661db93b..cb5c319f77 100644
--- a/src/libnm-client-public/NetworkManager.h
+++ b/src/libnm-client-public/NetworkManager.h
@@ -44,6 +44,7 @@
#include "nm-setting-ip6-config.h"
#include "nm-setting-ip-config.h"
#include "nm-setting-ip-tunnel.h"
+#include "nm-setting-link.h"
#include "nm-setting-loopback.h"
#include "nm-setting-macsec.h"
#include "nm-setting-macvlan.h"
diff --git a/src/libnm-client-public/nm-autoptr.h b/src/libnm-client-public/nm-autoptr.h
index 9020af1481..fde6cccf32 100644
--- a/src/libnm-client-public/nm-autoptr.h
+++ b/src/libnm-client-public/nm-autoptr.h
@@ -85,6 +85,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMSettingIP6Config, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMSettingIPConfig, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMSettingIPTunnel, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMSettingInfiniband, g_object_unref)
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMSettingLink, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMSettingLoopback, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMSettingMacsec, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMSettingMacvlan, g_object_unref)
diff --git a/src/libnm-core-impl/gen-metadata-nm-settings-libnm-core.xml.in b/src/libnm-core-impl/gen-metadata-nm-settings-libnm-core.xml.in
index 0559c2572f..c4133243ff 100644
--- a/src/libnm-core-impl/gen-metadata-nm-settings-libnm-core.xml.in
+++ b/src/libnm-core-impl/gen-metadata-nm-settings-libnm-core.xml.in
@@ -1749,6 +1749,26 @@
gprop-type="gchararray"
/>
</setting>
+ <setting name="link"
+ gtype="NMSettingLink"
+ >
+ <property name="gro-max-size"
+ dbus-type="x"
+ gprop-type="gint64"
+ />
+ <property name="gso-max-segments"
+ dbus-type="x"
+ gprop-type="gint64"
+ />
+ <property name="gso-max-size"
+ dbus-type="x"
+ gprop-type="gint64"
+ />
+ <property name="tx-queue-length"
+ dbus-type="x"
+ gprop-type="gint64"
+ />
+ </setting>
<setting name="loopback"
gtype="NMSettingLoopback"
>
diff --git a/src/libnm-core-impl/meson.build b/src/libnm-core-impl/meson.build
index 6408ae178a..635b417b7e 100644
--- a/src/libnm-core-impl/meson.build
+++ b/src/libnm-core-impl/meson.build
@@ -24,6 +24,7 @@ libnm_core_settings_sources = files(
'nm-setting-ip-tunnel.c',
'nm-setting-ip4-config.c',
'nm-setting-ip6-config.c',
+ 'nm-setting-link.c',
'nm-setting-loopback.c',
'nm-setting-macsec.c',
'nm-setting-macvlan.c',
diff --git a/src/libnm-core-impl/nm-meta-setting-base-impl.c b/src/libnm-core-impl/nm-meta-setting-base-impl.c
index 190826718a..b531ae85a3 100644
--- a/src/libnm-core-impl/nm-meta-setting-base-impl.c
+++ b/src/libnm-core-impl/nm-meta-setting-base-impl.c
@@ -34,6 +34,7 @@
#include "nm-setting-ip-tunnel.h"
#include "nm-setting-ip4-config.h"
#include "nm-setting-ip6-config.h"
+#include "nm-setting-link.h"
#include "nm-setting-loopback.h"
#include "nm-setting-macsec.h"
#include "nm-setting-macvlan.h"
@@ -362,6 +363,13 @@ const NMMetaSettingInfo nm_meta_setting_infos[] = {
.setting_name = NM_SETTING_IP_TUNNEL_SETTING_NAME,
.get_setting_gtype = nm_setting_ip_tunnel_get_type,
},
+ [NM_META_SETTING_TYPE_LINK] =
+ {
+ .meta_type = NM_META_SETTING_TYPE_LINK,
+ .setting_priority = NM_SETTING_PRIORITY_AUX,
+ .setting_name = NM_SETTING_LINK_SETTING_NAME,
+ .get_setting_gtype = nm_setting_link_get_type,
+ },
[NM_META_SETTING_TYPE_LOOPBACK] =
{
.meta_type = NM_META_SETTING_TYPE_LOOPBACK,
@@ -660,6 +668,7 @@ const NMMetaSettingType nm_meta_setting_types_by_priority[] = {
NM_META_SETTING_TYPE_BOND_PORT,
NM_META_SETTING_TYPE_BRIDGE_PORT,
NM_META_SETTING_TYPE_ETHTOOL,
+ NM_META_SETTING_TYPE_LINK,
NM_META_SETTING_TYPE_MATCH,
NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS,
NM_META_SETTING_TYPE_OVS_OTHER_CONFIG,
diff --git a/src/libnm-core-impl/nm-setting-link.c b/src/libnm-core-impl/nm-setting-link.c
new file mode 100644
index 0000000000..29d56d67eb
--- /dev/null
+++ b/src/libnm-core-impl/nm-setting-link.c
@@ -0,0 +1,241 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2023 Red Hat, Inc.
+ */
+
+#include "libnm-core-impl/nm-default-libnm-core.h"
+
+#include "nm-setting-link.h"
+
+#include "nm-setting-private.h"
+#include "nm-utils-private.h"
+
+/**
+ * SECTION:nm-setting-link
+ * @short_description: Contains properties related to the link
+ * @include: nm-setting-link.h
+ **/
+
+/*****************************************************************************/
+
+NM_GOBJECT_PROPERTIES_DEFINE(NMSettingLink,
+ PROP_TX_QUEUE_LENGTH,
+ PROP_GSO_MAX_SIZE,
+ PROP_GSO_MAX_SEGMENTS,
+ PROP_GRO_MAX_SIZE, );
+
+/**
+ * NMSettingLink:
+ *
+ * Link settings
+ *
+ * Since: 1.44
+ */
+struct _NMSettingLink {
+ NMSetting parent;
+ gint64 tx_queue_length;
+ gint64 gso_max_size;
+ gint64 gso_max_segments;
+ gint64 gro_max_size;
+};
+
+struct _NMSettingLinkClass {
+ NMSettingClass parent;
+};
+
+G_DEFINE_TYPE(NMSettingLink, nm_setting_link, NM_TYPE_SETTING)
+
+/**
+ * nm_setting_link_get_tx_queue_length:
+ * @setting: the #NMSettingLink
+ *
+ * Returns the value contained in the #NMSettingLink:tx-queue-length
+ * property.
+ *
+ * Returns: the 'tx-queue-length' property value
+ *
+ * Since: 1.44
+ **/
+gint64
+nm_setting_link_get_tx_queue_length(NMSettingLink *setting)
+{
+ g_return_val_if_fail(NM_IS_SETTING_LINK(setting), 0);
+
+ return setting->tx_queue_length;
+}
+
+/**
+ * nm_setting_link_get_gso_max_size:
+ * @setting: the #NMSettingLink
+ *
+ * Returns the value contained in the #NMSettingLink:gso-max-size
+ * property.
+ *
+ * Returns: the 'gso-max-size' property value
+ *
+ * Since: 1.44
+ **/
+gint64
+nm_setting_link_get_gso_max_size(NMSettingLink *setting)
+{
+ g_return_val_if_fail(NM_IS_SETTING_LINK(setting), 0);
+
+ return setting->gso_max_size;
+}
+
+/**
+ * nm_setting_link_get_gso_max_segments:
+ * @setting: the #NMSettingLink
+ *
+ * Returns the value contained in the #NMSettingLink:gso-max-segments
+ * property.
+ *
+ * Returns: the 'gso-max-segments' property value
+ *
+ * Since: 1.44
+ **/
+gint64
+nm_setting_link_get_gso_max_segments(NMSettingLink *setting)
+{
+ g_return_val_if_fail(NM_IS_SETTING_LINK(setting), 0);
+
+ return setting->gso_max_segments;
+}
+
+/**
+ * nm_setting_link_get_gro_max_size:
+ * @setting: the #NMSettingLink
+ *
+ * Returns the value contained in the #NMSettingLink:gro-max-size
+ * property.
+ *
+ * Returns: the 'gro-max-size' property value
+ *
+ * Since: 1.44
+ **/
+gint64
+nm_setting_link_get_gro_max_size(NMSettingLink *setting)
+{
+ g_return_val_if_fail(NM_IS_SETTING_LINK(setting), 0);
+
+ return setting->gro_max_size;
+}
+
+/*****************************************************************************/
+
+static void
+nm_setting_link_init(NMSettingLink *setting)
+{}
+
+/**
+ * nm_setting_link_new:
+ *
+ * Creates a new #NMSettingLink object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingLink object
+ *
+ * Since: 1.44
+ **/
+NMSetting *
+nm_setting_link_new(void)
+{
+ return g_object_new(NM_TYPE_SETTING_LINK, NULL);
+}
+
+static void
+nm_setting_link_class_init(NMSettingLinkClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS(klass);
+ NMSettingClass *setting_class = NM_SETTING_CLASS(klass);
+ GArray *properties_override = _nm_sett_info_property_override_create_array();
+
+ object_class->get_property = _nm_setting_property_get_property_direct;
+ object_class->set_property = _nm_setting_property_set_property_direct;
+
+ /**
+ * NMSettingLink:tx-queue-length
+ *
+ * The size of the transmit queue for the device, in number of packets. The value
+ * must be between 0 and 4294967295. When set to -1, the existing value is preserved.
+ *
+ * Since: 1.44
+ **/
+ _nm_setting_property_define_direct_int64(properties_override,
+ obj_properties,
+ NM_SETTING_LINK_TX_QUEUE_LENGTH,
+ PROP_TX_QUEUE_LENGTH,
+ -1,
+ G_MAXUINT32,
+ -1,
+ NM_SETTING_PARAM_NONE,
+ NMSettingLink,
+ tx_queue_length);
+
+ /**
+ * NMSettingLink:gso-max-size
+ *
+ * The maximum size of a Generic Segment Offload packet the device should accept.
+ * The value must be between 0 and 4294967295. When set to -1, the existing value
+ * is preserved.
+ *
+ * Since: 1.44
+ **/
+ _nm_setting_property_define_direct_int64(properties_override,
+ obj_properties,
+ NM_SETTING_LINK_GSO_MAX_SIZE,
+ PROP_GSO_MAX_SIZE,
+ -1,
+ G_MAXUINT32,
+ -1,
+ NM_SETTING_PARAM_NONE,
+ NMSettingLink,
+ gso_max_size);
+
+ /**
+ * NMSettingLink:gso-max-segments
+ *
+ * The maximum segments of a Generic Segment Offload packet the device should accept.
+ * The value must be between 0 and 4294967295. When set to -1, the existing value
+ * is preserved.
+ *
+ * Since: 1.44
+ **/
+ _nm_setting_property_define_direct_int64(properties_override,
+ obj_properties,
+ NM_SETTING_LINK_GSO_MAX_SEGMENTS,
+ PROP_GSO_MAX_SEGMENTS,
+ -1,
+ G_MAXUINT32,
+ -1,
+ NM_SETTING_PARAM_NONE,
+ NMSettingLink,
+ gso_max_segments);
+
+ /**
+ * NMSettingLink:gro-max-size
+ *
+ * The maximum size of a packet built by the Generic Receive Offload stack for
+ * this device. The value must be between 0 and 4294967295. When set to -1, the
+ * existing value is preserved.
+ *
+ * Since: 1.44
+ **/
+ _nm_setting_property_define_direct_int64(properties_override,
+ obj_properties,
+ NM_SETTING_LINK_GRO_MAX_SIZE,
+ PROP_GRO_MAX_SIZE,
+ -1,
+ G_MAXUINT32,
+ -1,
+ NM_SETTING_PARAM_NONE,
+ NMSettingLink,
+ gro_max_size);
+
+ g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
+
+ _nm_setting_class_commit(setting_class,
+ NM_META_SETTING_TYPE_LINK,
+ NULL,
+ properties_override,
+ 0);
+}
diff --git a/src/libnm-core-impl/tests/test-setting.c b/src/libnm-core-impl/tests/test-setting.c
index 09e0fc70ee..46e6818125 100644
--- a/src/libnm-core-impl/tests/test-setting.c
+++ b/src/libnm-core-impl/tests/test-setting.c
@@ -121,8 +121,6 @@ test_nm_meta_setting_types_by_priority(void)
G_STATIC_ASSERT_EXPR(_NM_META_SETTING_TYPE_NUM
== G_N_ELEMENTS(nm_meta_setting_types_by_priority));
- G_STATIC_ASSERT_EXPR(_NM_META_SETTING_TYPE_NUM == 54);
-
arr = g_ptr_array_new_with_free_func(g_object_unref);
for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) {
diff --git a/src/libnm-core-intern/nm-core-internal.h b/src/libnm-core-intern/nm-core-internal.h
index 71bbb0d499..3a56012323 100644
--- a/src/libnm-core-intern/nm-core-internal.h
+++ b/src/libnm-core-intern/nm-core-internal.h
@@ -43,6 +43,7 @@
#include "nm-setting-ip-tunnel.h"
#include "nm-setting-ip4-config.h"
#include "nm-setting-ip6-config.h"
+#include "nm-setting-link.h"
#include "nm-setting-loopback.h"
#include "nm-setting-macsec.h"
#include "nm-setting-macvlan.h"
diff --git a/src/libnm-core-intern/nm-meta-setting-base-impl.h b/src/libnm-core-intern/nm-meta-setting-base-impl.h
index 0c2def90cd..c6d1c2fcb6 100644
--- a/src/libnm-core-intern/nm-meta-setting-base-impl.h
+++ b/src/libnm-core-intern/nm-meta-setting-base-impl.h
@@ -127,6 +127,7 @@ typedef enum _nm_packed {
NM_META_SETTING_TYPE_IP_TUNNEL,
NM_META_SETTING_TYPE_IP4_CONFIG,
NM_META_SETTING_TYPE_IP6_CONFIG,
+ NM_META_SETTING_TYPE_LINK,
NM_META_SETTING_TYPE_LOOPBACK,
NM_META_SETTING_TYPE_MACSEC,
NM_META_SETTING_TYPE_MACVLAN,
diff --git a/src/libnm-core-public/meson.build b/src/libnm-core-public/meson.build
index c54071303c..d135dbff94 100644
--- a/src/libnm-core-public/meson.build
+++ b/src/libnm-core-public/meson.build
@@ -29,6 +29,7 @@ libnm_core_headers = files(
'nm-setting-ip-tunnel.h',
'nm-setting-ip4-config.h',
'nm-setting-ip6-config.h',
+ 'nm-setting-link.h',
'nm-setting-loopback.h',
'nm-setting-macsec.h',
'nm-setting-macvlan.h',
diff --git a/src/libnm-core-public/nm-core-types.h b/src/libnm-core-public/nm-core-types.h
index f285a0f6f1..758733a1cc 100644
--- a/src/libnm-core-public/nm-core-types.h
+++ b/src/libnm-core-public/nm-core-types.h
@@ -35,6 +35,7 @@ typedef struct _NMSettingIP6Config NMSettingIP6Config;
typedef struct _NMSettingIPConfig NMSettingIPConfig;
typedef struct _NMSettingIPTunnel NMSettingIPTunnel;
typedef struct _NMSettingInfiniband NMSettingInfiniband;
+typedef struct _NMSettingLink NMSettingLink;
typedef struct _NMSettingLoopback NMSettingLoopback;
typedef struct _NMSettingMacsec NMSettingMacsec;
typedef struct _NMSettingMacvlan NMSettingMacvlan;
diff --git a/src/libnm-core-public/nm-setting-link.h b/src/libnm-core-public/nm-setting-link.h
new file mode 100644
index 0000000000..98973ff568
--- /dev/null
+++ b/src/libnm-core-public/nm-setting-link.h
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2020 Red Hat, Inc.
+ */
+
+#ifndef __NM_SETTING_LINK_H__
+#define __NM_SETTING_LINK_H__
+
+#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION)
+#error "Only <NetworkManager.h> can be included directly."
+#endif
+
+#include "nm-setting.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_SETTING_LINK (nm_setting_link_get_type())
+#define NM_SETTING_LINK(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_LINK, NMSettingLink))
+#define NM_SETTING_LINK_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_LINK, NMSettingLinkClass))
+#define NM_IS_SETTING_LINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_LINK))
+#define NM_IS_SETTING_LINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_LINK))
+#define NM_SETTING_LINK_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_LINK, NMSettingLinkClass))
+
+#define NM_SETTING_LINK_SETTING_NAME "link"
+
+#define NM_SETTING_LINK_TX_QUEUE_LENGTH "tx-queue-length"
+#define NM_SETTING_LINK_GSO_MAX_SIZE "gso-max-size"
+#define NM_SETTING_LINK_GSO_MAX_SEGMENTS "gso-max-segments"
+#define NM_SETTING_LINK_GRO_MAX_SIZE "gro-max-size"
+
+typedef struct _NMSettingLinkClass NMSettingLinkClass;
+
+NM_AVAILABLE_IN_1_44
+GType nm_setting_link_get_type(void);
+NM_AVAILABLE_IN_1_44
+NMSetting *nm_setting_link_new(void);
+
+NM_AVAILABLE_IN_1_44
+gint64 nm_setting_link_get_tx_queue_length(NMSettingLink *setting);
+NM_AVAILABLE_IN_1_44
+gint64 nm_setting_link_get_gso_max_size(NMSettingLink *setting);
+NM_AVAILABLE_IN_1_44
+gint64 nm_setting_link_get_gso_max_segments(NMSettingLink *setting);
+NM_AVAILABLE_IN_1_44
+gint64 nm_setting_link_get_gro_max_size(NMSettingLink *setting);
+
+G_END_DECLS
+
+#endif /* __NM_SETTING_LINK_H__ */
diff --git a/src/libnm-platform/nm-linux-platform.c b/src/libnm-platform/nm-linux-platform.c
index 78d6e704bb..94e92a9bec 100644
--- a/src/libnm-platform/nm-linux-platform.c
+++ b/src/libnm-platform/nm-linux-platform.c
@@ -115,7 +115,9 @@ typedef enum _nm_packed {
#define IFLA_CARRIER 33
#define IFLA_PHYS_PORT_ID 34
#define IFLA_LINK_NETNSID 37
-#define __IFLA_MAX 39
+#define IFLA_GSO_MAX_SEGS 40
+#define IFLA_GSO_MAX_SIZE 41
+#define IFLA_GRO_MAX_SIZE 58
#define IFLA_INET6_TOKEN 7
#define IFLA_INET6_ADDR_GEN_MODE 8
@@ -3260,6 +3262,9 @@ _new_from_nl_link(NMPlatform *platform,
[IFLA_IFNAME] = {.type = NLA_STRING, .maxlen = IFNAMSIZ},
[IFLA_MTU] = {.type = NLA_U32},
[IFLA_TXQLEN] = {.type = NLA_U32},
+ [IFLA_GSO_MAX_SIZE] = {.type = NLA_U32},
+ [IFLA_GSO_MAX_SEGS] = {.type = NLA_U32},
+ [IFLA_GRO_MAX_SIZE] = {.type = NLA_U32},
[IFLA_LINK] = {.type = NLA_U32},
[IFLA_WEIGHT] = {.type = NLA_U32},
[IFLA_MASTER] = {.type = NLA_U32},
@@ -3359,6 +3364,15 @@ _new_from_nl_link(NMPlatform *platform,
nl_info_data = li[IFLA_INFO_DATA];
}
+ if (tb[IFLA_TXQLEN])
+ obj->link.link_props.tx_queue_length = nla_get_u32(tb[IFLA_TXQLEN]);
+ if (tb[IFLA_GSO_MAX_SIZE])
+ obj->link.link_props.gso_max_size = nla_get_u32(tb[IFLA_GSO_MAX_SIZE]);
+ if (tb[IFLA_GSO_MAX_SEGS])
+ obj->link.link_props.gso_max_segments = nla_get_u32(tb[IFLA_GSO_MAX_SEGS]);
+ if (tb[IFLA_GRO_MAX_SIZE])
+ obj->link.link_props.gro_max_size = nla_get_u32(tb[IFLA_GRO_MAX_SIZE]);
+
if (tb[IFLA_STATS64]) {
const char *stats = nla_data(tb[IFLA_STATS64]);
@@ -8270,7 +8284,7 @@ out:
}
static int
-link_change(NMPlatform *platform, NMLinkType type, int ifindex, gconstpointer extra_data)
+link_change_extra(NMPlatform *platform, NMLinkType type, int ifindex, gconstpointer extra_data)
{
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
@@ -8348,6 +8362,32 @@ link_delete(NMPlatform *platform, int ifindex)
}
static gboolean
+link_change(NMPlatform *platform,
+ int ifindex,
+ NMPlatformLinkProps *props,
+ NMPlatformLinkChangeFlags flags)
+{
+ nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
+
+ nlmsg = _nl_msg_new_link(RTM_NEWLINK, 0, ifindex, NULL);
+ if (!nlmsg)
+ return FALSE;
+
+ if (flags & NM_PLATFORM_LINK_CHANGE_TX_QUEUE_LENGTH)
+ NLA_PUT_U32(nlmsg, IFLA_TXQLEN, props->tx_queue_length);
+ if (flags & NM_PLATFORM_LINK_CHANGE_GSO_MAX_SIZE)
+ NLA_PUT_U32(nlmsg, IFLA_GSO_MAX_SIZE, props->gso_max_size);
+ if (flags & NM_PLATFORM_LINK_CHANGE_GSO_MAX_SEGMENTS)
+ NLA_PUT_U32(nlmsg, IFLA_GSO_MAX_SEGS, props->gso_max_segments);
+ if (flags & NM_PLATFORM_LINK_CHANGE_GRO_MAX_SIZE)
+ NLA_PUT_U32(nlmsg, IFLA_GRO_MAX_SIZE, props->gro_max_size);
+
+ return do_change_link(platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL) == 0;
+nla_put_failure:
+ g_return_val_if_reached(FALSE);
+}
+
+static gboolean
link_refresh(NMPlatform *platform, int ifindex)
{
do_request_link(platform, ifindex, NULL);
@@ -11166,9 +11206,11 @@ nm_linux_platform_class_init(NMLinuxPlatformClass *klass)
platform_class->sysctl_set_async = sysctl_set_async;
platform_class->sysctl_get = sysctl_get;
- platform_class->link_add = link_add;
+ platform_class->link_add = link_add;
+ platform_class->link_change_extra = link_change_extra;
+ platform_class->link_delete = link_delete;
+
platform_class->link_change = link_change;
- platform_class->link_delete = link_delete;
platform_class->link_refresh = link_refresh;
diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c
index 64d0fd8efd..06c1f4a741 100644
--- a/src/libnm-platform/nm-platform.c
+++ b/src/libnm-platform/nm-platform.c
@@ -1406,7 +1406,10 @@ nm_platform_link_add(NMPlatform *self,
}
int
-nm_platform_link_change(NMPlatform *self, NMLinkType type, int ifindex, gconstpointer extra_data)
+nm_platform_link_change_extra(NMPlatform *self,
+ NMLinkType type,
+ int ifindex,
+ gconstpointer extra_data)
{
char buf[512];
const char *name = nm_platform_link_get_name(self, ifindex);
@@ -1447,7 +1450,7 @@ nm_platform_link_change(NMPlatform *self, NMLinkType type, int ifindex, gconstpo
buf;
}));
- return klass->link_change(self, type, ifindex, extra_data);
+ return klass->link_change_extra(self, type, ifindex, extra_data);
}
/**
@@ -2130,6 +2133,40 @@ nm_platform_link_set_name(NMPlatform *self, int ifindex, const char *name)
return klass->link_set_name(self, ifindex, name);
}
+gboolean
+nm_platform_link_change(NMPlatform *self,
+ int ifindex,
+ NMPlatformLinkProps *props,
+ NMPlatformLinkChangeFlags flags)
+{
+ _CHECK_SELF(self, klass, FALSE);
+
+ g_return_val_if_fail(ifindex >= 0, FALSE);
+
+ if (flags == 0)
+ return TRUE;
+
+ if (_LOGD_ENABLED()) {
+ nm_auto_free_gstring GString *str = g_string_new("");
+
+ if (flags & NM_PLATFORM_LINK_CHANGE_TX_QUEUE_LENGTH)
+ g_string_append_printf(str, "tx-queue-length %u ", props->tx_queue_length);
+ if (flags & NM_PLATFORM_LINK_CHANGE_GSO_MAX_SIZE)
+ g_string_append_printf(str, "gso_max_size %u ", props->gso_max_size);
+ if (flags & NM_PLATFORM_LINK_CHANGE_GSO_MAX_SEGMENTS)
+ g_string_append_printf(str, "gso_max_segments %u ", props->gso_max_segments);
+ if (flags & NM_PLATFORM_LINK_CHANGE_GRO_MAX_SIZE)
+ g_string_append_printf(str, "gro_max_size %u ", props->gro_max_size);
+
+ if (str->len > 0 && str->str[str->len - 1] == ' ')
+ g_string_truncate(str, str->len - 1);
+
+ _LOG3D("link: change: %s", str->str);
+ }
+
+ return klass->link_change(self, ifindex, props, flags);
+}
+
/**
* nm_platform_link_get_physical_port_id:
* @self: platform instance
@@ -6015,6 +6052,10 @@ nm_platform_link_to_string(const NMPlatformLink *link, char *buf, gsize len)
"%s%s" /* l_broadcast */
"%s%s" /* inet6_token */
"%s%s" /* driver */
+ " tx-queue-len %u"
+ " gso-max-size %u"
+ " gso-max-segs %u"
+ " gro-max-size %u"
" rx:%" G_GUINT64_FORMAT ",%" G_GUINT64_FORMAT " tx:%" G_GUINT64_FORMAT
",%" G_GUINT64_FORMAT,
link->ifindex,
@@ -6047,6 +6088,10 @@ nm_platform_link_to_string(const NMPlatformLink *link, char *buf, gsize len)
: "",
link->driver ? " driver " : "",
link->driver ?: "",
+ link->link_props.tx_queue_length,
+ link->link_props.gso_max_size,
+ link->link_props.gso_max_segments,
+ link->link_props.gro_max_size,
link->rx_packets,
link->rx_bytes,
link->tx_packets,
@@ -7879,6 +7924,10 @@ nm_platform_link_hash_update(const NMPlatformLink *obj, NMHashState *h)
obj->arptype,
obj->inet6_addr_gen_mode_inv,
obj->inet6_token,
+ obj->link_props.tx_queue_length,
+ obj->link_props.gso_max_size,
+ obj->link_props.gso_max_segments,
+ obj->link_props.gro_max_size,
obj->rx_packets,
obj->rx_bytes,
obj->tx_packets,
@@ -7926,6 +7975,10 @@ nm_platform_link_cmp(const NMPlatformLink *a, const NMPlatformLink *b)
if (a->l_broadcast.len)
NM_CMP_FIELD_MEMCMP_LEN(a, b, l_broadcast.data, a->l_broadcast.len);
NM_CMP_FIELD_MEMCMP(a, b, inet6_token);
+ NM_CMP_FIELD(a, b, link_props.tx_queue_length);
+ NM_CMP_FIELD(a, b, link_props.gso_max_size);
+ NM_CMP_FIELD(a, b, link_props.gso_max_segments);
+ NM_CMP_FIELD(a, b, link_props.gro_max_size);
NM_CMP_FIELD(a, b, rx_packets);
NM_CMP_FIELD(a, b, rx_bytes);
NM_CMP_FIELD(a, b, tx_packets);
diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h
index 447ef3aa8f..d816513cd0 100644
--- a/src/libnm-platform/nm-platform.h
+++ b/src/libnm-platform/nm-platform.h
@@ -150,6 +150,21 @@ GBytes *nmp_link_address_get_as_bytes(const NMPLinkAddress *addr);
#define NM_PLATFORM_LINK_OTHER_NETNS (-1)
+typedef struct {
+ guint32 tx_queue_length;
+ guint32 gso_max_size;
+ guint32 gso_max_segments;
+ guint32 gro_max_size;
+} NMPlatformLinkProps;
+
+typedef enum {
+ NM_PLATFORM_LINK_CHANGE_NONE = 0,
+ NM_PLATFORM_LINK_CHANGE_TX_QUEUE_LENGTH = (1 << 0),
+ NM_PLATFORM_LINK_CHANGE_GSO_MAX_SIZE = (1 << 1),
+ NM_PLATFORM_LINK_CHANGE_GSO_MAX_SEGMENTS = (1 << 2),
+ NM_PLATFORM_LINK_CHANGE_GRO_MAX_SIZE = (1 << 3),
+} NMPlatformLinkChangeFlags;
+
struct _NMPlatformObjWithIfindex {
__NMPlatformObjWithIfindex_COMMON;
} _nm_alignas(NMPlatformObject);
@@ -204,6 +219,8 @@ struct _NMPlatformLink {
guint64 tx_packets;
guint64 tx_bytes;
+ NMPlatformLinkProps link_props;
+
/* @connected is mostly identical to (@n_ifi_flags & IFF_UP). Except for bridge/bond masters,
* where we coerce the link as disconnect if it has no slaves. */
bool connected : 1;
@@ -1093,9 +1110,14 @@ typedef struct {
guint32 mtu,
gconstpointer extra_data,
const NMPlatformLink **out_link);
-
- int (*link_change)(NMPlatform *self, NMLinkType type, int ifindex, gconstpointer extra_data);
-
+ int (*link_change_extra)(NMPlatform *self,
+ NMLinkType type,
+ int ifindex,
+ gconstpointer extra_data);
+ gboolean (*link_change)(NMPlatform *self,
+ int ifindex,
+ NMPlatformLinkProps *props,
+ NMPlatformLinkChangeFlags flags);
gboolean (*link_delete)(NMPlatform *self, int ifindex);
gboolean (*link_refresh)(NMPlatform *self, int ifindex);
gboolean (*link_set_netns)(NMPlatform *self, int ifindex, int netns_fd);
@@ -1603,8 +1625,10 @@ int nm_platform_link_add(NMPlatform *self,
gconstpointer extra_data,
const NMPlatformLink **out_link);
-int
-nm_platform_link_change(NMPlatform *self, NMLinkType type, int ifindex, gconstpointer extra_data);
+int nm_platform_link_change_extra(NMPlatform *self,
+ NMLinkType type,
+ int ifindex,
+ gconstpointer extra_data);
static inline int
nm_platform_link_veth_add(NMPlatform *self,
@@ -1644,13 +1668,13 @@ nm_platform_link_bridge_add(NMPlatform *self,
static inline int
nm_platform_link_bridge_change(NMPlatform *self, int ifindex, const NMPlatformLnkBridge *props)
{
- return nm_platform_link_change(self, NM_LINK_TYPE_BRIDGE, ifindex, props);
+ return nm_platform_link_change_extra(self, NM_LINK_TYPE_BRIDGE, ifindex, props);
}
static inline int
nm_platform_link_bond_change(NMPlatform *self, int ifindex, const NMPlatformLnkBond *props)
{
- return nm_platform_link_change(self, NM_LINK_TYPE_BOND, ifindex, props);
+ return nm_platform_link_change_extra(self, NM_LINK_TYPE_BOND, ifindex, props);
}
static inline int
@@ -1927,6 +1951,11 @@ nm_platform_link_change_flags(NMPlatform *self, int ifindex, unsigned value, gbo
return nm_platform_link_change_flags_full(self, ifindex, value, set ? value : 0u);
}
+gboolean nm_platform_link_change(NMPlatform *self,
+ int ifindex,
+ NMPlatformLinkProps *props,
+ NMPlatformLinkChangeFlags flags);
+
gboolean nm_platform_link_get_udev_property(NMPlatform *self,
int ifindex,
const char *name,
diff --git a/src/libnmc-setting/nm-meta-setting-base-impl.c b/src/libnmc-setting/nm-meta-setting-base-impl.c
index 190826718a..b531ae85a3 100644
--- a/src/libnmc-setting/nm-meta-setting-base-impl.c
+++ b/src/libnmc-setting/nm-meta-setting-base-impl.c
@@ -34,6 +34,7 @@
#include "nm-setting-ip-tunnel.h"
#include "nm-setting-ip4-config.h"
#include "nm-setting-ip6-config.h"
+#include "nm-setting-link.h"
#include "nm-setting-loopback.h"
#include "nm-setting-macsec.h"
#include "nm-setting-macvlan.h"
@@ -362,6 +363,13 @@ const NMMetaSettingInfo nm_meta_setting_infos[] = {
.setting_name = NM_SETTING_IP_TUNNEL_SETTING_NAME,
.get_setting_gtype = nm_setting_ip_tunnel_get_type,
},
+ [NM_META_SETTING_TYPE_LINK] =
+ {
+ .meta_type = NM_META_SETTING_TYPE_LINK,
+ .setting_priority = NM_SETTING_PRIORITY_AUX,
+ .setting_name = NM_SETTING_LINK_SETTING_NAME,
+ .get_setting_gtype = nm_setting_link_get_type,
+ },
[NM_META_SETTING_TYPE_LOOPBACK] =
{
.meta_type = NM_META_SETTING_TYPE_LOOPBACK,
@@ -660,6 +668,7 @@ const NMMetaSettingType nm_meta_setting_types_by_priority[] = {
NM_META_SETTING_TYPE_BOND_PORT,
NM_META_SETTING_TYPE_BRIDGE_PORT,
NM_META_SETTING_TYPE_ETHTOOL,
+ NM_META_SETTING_TYPE_LINK,
NM_META_SETTING_TYPE_MATCH,
NM_META_SETTING_TYPE_OVS_EXTERNAL_IDS,
NM_META_SETTING_TYPE_OVS_OTHER_CONFIG,
diff --git a/src/libnmc-setting/nm-meta-setting-base-impl.h b/src/libnmc-setting/nm-meta-setting-base-impl.h
index 0c2def90cd..c6d1c2fcb6 100644
--- a/src/libnmc-setting/nm-meta-setting-base-impl.h
+++ b/src/libnmc-setting/nm-meta-setting-base-impl.h
@@ -127,6 +127,7 @@ typedef enum _nm_packed {
NM_META_SETTING_TYPE_IP_TUNNEL,
NM_META_SETTING_TYPE_IP4_CONFIG,
NM_META_SETTING_TYPE_IP6_CONFIG,
+ NM_META_SETTING_TYPE_LINK,
NM_META_SETTING_TYPE_LOOPBACK,
NM_META_SETTING_TYPE_MACSEC,
NM_META_SETTING_TYPE_MACVLAN,
diff --git a/src/libnmc-setting/nm-meta-setting-desc.c b/src/libnmc-setting/nm-meta-setting-desc.c
index 46bc818fa5..60a2cfd402 100644
--- a/src/libnmc-setting/nm-meta-setting-desc.c
+++ b/src/libnmc-setting/nm-meta-setting-desc.c
@@ -6649,6 +6649,56 @@ static const NMMetaPropertyInfo *const property_infos_LOOPBACK[] = {
};
#undef _CURRENT_NM_META_SETTING_TYPE
+#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_LINK
+static const NMMetaPropertyInfo *const property_infos_LINK[] = {
+ PROPERTY_INFO_WITH_DESC (NM_SETTING_LINK_GSO_MAX_SEGMENTS,
+ .property_type = &_pt_gobject_int,
+ .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int,
+ .value_infos = INT_VALUE_INFOS (
+ {
+ .value.i64 = -1,
+ .nick = "default",
+ },
+ ),
+ ),
+ ),
+ PROPERTY_INFO_WITH_DESC (NM_SETTING_LINK_GSO_MAX_SIZE,
+ .property_type = &_pt_gobject_int,
+ .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int,
+ .value_infos = INT_VALUE_INFOS (
+ {
+ .value.i64 = -1,
+ .nick = "default",
+ },
+ ),
+ ),
+ ),
+ PROPERTY_INFO_WITH_DESC (NM_SETTING_LINK_GRO_MAX_SIZE,
+ .property_type = &_pt_gobject_int,
+ .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int,
+ .value_infos = INT_VALUE_INFOS (
+ {
+ .value.i64 = -1,
+ .nick = "default",
+ },
+ ),
+ ),
+ ),
+ PROPERTY_INFO_WITH_DESC (NM_SETTING_LINK_TX_QUEUE_LENGTH,
+ .property_type = &_pt_gobject_int,
+ .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int,
+ .value_infos = INT_VALUE_INFOS (
+ {
+ .value.i64 = -1,
+ .nick = "default",
+ },
+ ),
+ ),
+ ),
+ NULL
+};
+
+#undef _CURRENT_NM_META_SETTING_TYPE
#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_MACSEC
static const NMMetaPropertyInfo *const property_infos_MACSEC[] = {
PROPERTY_INFO_WITH_DESC (NM_SETTING_MACSEC_PARENT,
@@ -8427,6 +8477,7 @@ _setting_init_fcn_wireless (ARGS_SETTING_INIT_FCN)
#define SETTING_PRETTY_NAME_IP4_CONFIG N_("IPv4 protocol")
#define SETTING_PRETTY_NAME_IP6_CONFIG N_("IPv6 protocol")
#define SETTING_PRETTY_NAME_IP_TUNNEL N_("IP-tunnel settings")
+#define SETTING_PRETTY_NAME_LINK N_("Link settings")
#define SETTING_PRETTY_NAME_LOOPBACK N_("Loopback settings")
#define SETTING_PRETTY_NAME_MACSEC N_("MACsec connection")
#define SETTING_PRETTY_NAME_MACVLAN N_("macvlan connection")
@@ -8588,6 +8639,7 @@ const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = {
NM_META_SETTING_VALID_PART_ITEM (ETHTOOL, FALSE),
),
),
+ SETTING_INFO (LINK),
SETTING_INFO (LOOPBACK,
.valid_parts = NM_META_SETTING_VALID_PARTS (
NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE),
@@ -8802,6 +8854,7 @@ static const NMMetaSettingValidPartItem *const valid_settings_noslave[] = {
NM_META_SETTING_VALID_PART_ITEM(IP4_CONFIG, FALSE),
NM_META_SETTING_VALID_PART_ITEM(IP6_CONFIG, FALSE),
NM_META_SETTING_VALID_PART_ITEM(HOSTNAME, FALSE),
+ NM_META_SETTING_VALID_PART_ITEM(LINK, FALSE),
NM_META_SETTING_VALID_PART_ITEM(TC_CONFIG, FALSE),
NM_META_SETTING_VALID_PART_ITEM(PROXY, FALSE),
NULL,
@@ -8809,11 +8862,15 @@ static const NMMetaSettingValidPartItem *const valid_settings_noslave[] = {
static const NMMetaSettingValidPartItem *const valid_settings_slave_bond[] = {
NM_META_SETTING_VALID_PART_ITEM(BOND_PORT, TRUE),
+ NM_META_SETTING_VALID_PART_ITEM(LINK, FALSE),
+ NM_META_SETTING_VALID_PART_ITEM(MATCH, FALSE),
NULL,
};
static const NMMetaSettingValidPartItem *const valid_settings_slave_bridge[] = {
NM_META_SETTING_VALID_PART_ITEM(BRIDGE_PORT, TRUE),
+ NM_META_SETTING_VALID_PART_ITEM(LINK, FALSE),
+ NM_META_SETTING_VALID_PART_ITEM(MATCH, FALSE),
NULL,
};
@@ -8823,11 +8880,15 @@ static const NMMetaSettingValidPartItem *const valid_settings_slave_ovs_bridge[]
};
static const NMMetaSettingValidPartItem *const valid_settings_slave_ovs_port[] = {
+ NM_META_SETTING_VALID_PART_ITEM(LINK, FALSE),
+ NM_META_SETTING_VALID_PART_ITEM(MATCH, FALSE),
NM_META_SETTING_VALID_PART_ITEM(OVS_INTERFACE, FALSE),
NULL,
};
static const NMMetaSettingValidPartItem *const valid_settings_slave_team[] = {
+ NM_META_SETTING_VALID_PART_ITEM(LINK, FALSE),
+ NM_META_SETTING_VALID_PART_ITEM(MATCH, FALSE),
NM_META_SETTING_VALID_PART_ITEM(TEAM_PORT, TRUE),
NULL,
};
diff --git a/src/libnmc-setting/settings-docs.h.in b/src/libnmc-setting/settings-docs.h.in
index ece3cfc831..8c8741d166 100644
--- a/src/libnmc-setting/settings-docs.h.in
+++ b/src/libnmc-setting/settings-docs.h.in
@@ -443,6 +443,10 @@
#define DESCRIBE_DOC_NM_SETTING_HOSTNAME_FROM_DNS_LOOKUP N_("Whether the system hostname can be determined from reverse DNS lookup of addresses on this device. When set to NM_TERNARY_DEFAULT (-1), the value from global configuration is used. If the property doesn't have a value in the global configuration, NetworkManager assumes the value to be NM_TERNARY_TRUE (1).")
#define DESCRIBE_DOC_NM_SETTING_HOSTNAME_ONLY_FROM_DEFAULT N_("If set to NM_TERNARY_TRUE (1), NetworkManager attempts to get the hostname via DHCPv4/DHCPv6 or reverse DNS lookup on this device only when the device has the default route for the given address family (IPv4/IPv6). If set to NM_TERNARY_FALSE (0), the hostname can be set from this device even if it doesn't have the default route. When set to NM_TERNARY_DEFAULT (-1), the value from global configuration is used. If the property doesn't have a value in the global configuration, NetworkManager assumes the value to be NM_TERNARY_FALSE (0).")
#define DESCRIBE_DOC_NM_SETTING_HOSTNAME_PRIORITY N_("The relative priority of this connection to determine the system hostname. A lower numerical value is better (higher priority). A connection with higher priority is considered before connections with lower priority. If the value is zero, it can be overridden by a global value from NetworkManager configuration. If the property doesn't have a value in the global configuration, the value is assumed to be 100. Negative values have the special effect of excluding other connections with a greater numerical priority value; so in presence of at least one negative priority, only connections with the lowest priority value will be used to determine the hostname.")
+#define DESCRIBE_DOC_NM_SETTING_LINK_GRO_MAX_SIZE N_("The maximum size of a packet built by the Generic Receive Offload stack for this device. The value must be between 0 and 4294967295. When set to -1, the existing value is preserved.")
+#define DESCRIBE_DOC_NM_SETTING_LINK_GSO_MAX_SEGMENTS N_("The maximum segments of a Generic Segment Offload packet the device should accept. The value must be between 0 and 4294967295. When set to -1, the existing value is preserved.")
+#define DESCRIBE_DOC_NM_SETTING_LINK_GSO_MAX_SIZE N_("The maximum size of a Generic Segment Offload packet the device should accept. The value must be between 0 and 4294967295. When set to -1, the existing value is preserved.")
+#define DESCRIBE_DOC_NM_SETTING_LINK_TX_QUEUE_LENGTH N_("The size of the transmit queue for the device, in number of packets. The value must be between 0 and 4294967295. When set to -1, the existing value is preserved.")
#define DESCRIBE_DOC_NM_SETTING_LOOPBACK_MTU N_("If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple Ethernet frames.")
#define DESCRIBE_DOC_NM_SETTING_OVS_EXTERNAL_IDS_DATA N_("A dictionary of key/value pairs with external-ids for OVS.")
#define DESCRIBE_DOC_NM_SETTING_OVS_OTHER_CONFIG_DATA N_("A dictionary of key/value pairs with other_config settings for OVS. See also \"other_config\" in the \"ovs-vswitchd.conf.db\" manual for the keys that OVS supports.")
diff --git a/src/nmcli/connections.c b/src/nmcli/connections.c
index 36de6373e9..5de64727b3 100644
--- a/src/nmcli/connections.c
+++ b/src/nmcli/connections.c
@@ -1046,9 +1046,9 @@ const NmcMetaGenericInfo
"," NM_SETTING_MACVLAN_SETTING_NAME "," NM_SETTING_VXLAN_SETTING_NAME \
"," NM_SETTING_VRF_SETTING_NAME "," NM_SETTING_WPAN_SETTING_NAME \
"," NM_SETTING_6LOWPAN_SETTING_NAME "," NM_SETTING_WIREGUARD_SETTING_NAME \
- "," NM_SETTING_PROXY_SETTING_NAME "," NM_SETTING_TC_CONFIG_SETTING_NAME \
- "," NM_SETTING_SRIOV_SETTING_NAME "," NM_SETTING_ETHTOOL_SETTING_NAME \
- "," NM_SETTING_OVS_DPDK_SETTING_NAME \
+ "," NM_SETTING_LINK_SETTING_NAME "," NM_SETTING_PROXY_SETTING_NAME \
+ "," NM_SETTING_TC_CONFIG_SETTING_NAME "," NM_SETTING_SRIOV_SETTING_NAME \
+ "," NM_SETTING_ETHTOOL_SETTING_NAME "," NM_SETTING_OVS_DPDK_SETTING_NAME \
"," NM_SETTING_HOSTNAME_SETTING_NAME /* NM_SETTING_DUMMY_SETTING_NAME NM_SETTING_WIMAX_SETTING_NAME */
const NmcMetaGenericInfo *const nmc_fields_con_active_details_groups[] = {
diff --git a/src/nmcli/gen-metadata-nm-settings-nmcli.xml.in b/src/nmcli/gen-metadata-nm-settings-nmcli.xml.in
index 66815d2697..41d6c2bd13 100644
--- a/src/nmcli/gen-metadata-nm-settings-nmcli.xml.in
+++ b/src/nmcli/gen-metadata-nm-settings-nmcli.xml.in
@@ -776,6 +776,16 @@
<property name="token"
description="Configure the token for draft-chown-6man-tokenised-ipv6-identifiers-02 IPv6 tokenized interface identifiers. Useful with eui64 addr-gen-mode." />
</setting>
+ <setting name="link" >
+ <property name="gso-max-segments"
+ description="The maximum segments of a Generic Segment Offload packet the device should accept. The value must be between 0 and 4294967295. When set to -1, the existing value is preserved." />
+ <property name="gso-max-size"
+ description="The maximum size of a Generic Segment Offload packet the device should accept. The value must be between 0 and 4294967295. When set to -1, the existing value is preserved." />
+ <property name="gro-max-size"
+ description="The maximum size of a packet built by the Generic Receive Offload stack for this device. The value must be between 0 and 4294967295. When set to -1, the existing value is preserved." />
+ <property name="tx-queue-length"
+ description="The size of the transmit queue for the device, in number of packets. The value must be between 0 and 4294967295. When set to -1, the existing value is preserved." />
+ </setting>
<setting name="loopback" >
<property name="mtu"
alias="mtu"
diff --git a/vapi/NM-1.0.metadata b/vapi/NM-1.0.metadata
index 48df877b51..44e2674e70 100644
--- a/vapi/NM-1.0.metadata
+++ b/vapi/NM-1.0.metadata
@@ -36,6 +36,7 @@ SETTING_IP4_CONFIG_* parent="NM.SettingIP4Config" name="SETTIN
SETTING_IP6_CONFIG_* parent="NM.SettingIP6Config" name="SETTING_IP6_CONFIG_(.+)"
SETTING_IP_CONFIG_* parent="NM.SettingIPConfig" name="SETTING_IP_CONFIG_(.+)"
SETTING_IP_TUNNEL_* parent="NM.SettingIPTunnel" name="SETTING_IP_TUNNEL_(.+)"
+SETTING_LINK_* parent="NM.SettingLink" name="SETTING_LINK_(.+)"
SETTING_LOOPBACK_* parent="NM.SettingLoopback" name="SETTING_LOOPBACK_(.+)"
SETTING_MACSEC_* parent="NM.SettingMacsec" name="SETTING_MACSEC_(.+)"
SETTING_MACVLAN_* parent="NM.SettingMacvlan" name="SETTING_MACVLAN_(.+)"