platform: support changing link properties

Add support in platform for changing the newly introduced link
properties.
This commit is contained in:
Beniamino Galvani
2023-02-16 16:37:54 +01:00
parent 39bfcf7aab
commit e02fd76d9f
4 changed files with 150 additions and 1 deletions

View File

@@ -2582,6 +2582,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)
{
@@ -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);

View File

@@ -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]);
@@ -8347,6 +8361,32 @@ link_delete(NMPlatform *platform, int ifindex)
return do_delete_object(platform, &obj_id, nlmsg);
}
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)
{
@@ -11170,6 +11210,8 @@ nm_linux_platform_class_init(NMLinuxPlatformClass *klass)
platform_class->link_change_extra = link_change_extra;
platform_class->link_delete = link_delete;
platform_class->link_change = link_change;
platform_class->link_refresh = link_refresh;
platform_class->link_set_netns = link_set_netns;

View File

@@ -2133,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
@@ -6018,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,
@@ -6050,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,
@@ -7882,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,
@@ -7929,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);

View File

@@ -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;
@@ -1097,6 +1114,10 @@ typedef struct {
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);
@@ -1930,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,