diff options
author | Fernando Fernandez Mancera <ffmancera@riseup.net> | 2023-03-03 16:36:23 +0100 |
---|---|---|
committer | Fernando Fernandez Mancera <ffmancera@riseup.net> | 2023-05-03 09:55:45 +0200 |
commit | bb435674b56e876084d4c31138ea95cb3174759f (patch) | |
tree | fe039e8032eafa074dae99383d8d34781ff15ba3 | |
parent | 762cd06ffa4ff56b096128c26c931843429dc8c5 (diff) | |
download | NetworkManager-bb435674b56e876084d4c31138ea95cb3174759f.tar.gz |
platform: add netlink support for bond port options
sysfs is deprecated and kernel will not add new bond port options to
sysfs. Netlink is a stable API and therefore is the right method to
communicate with kernel in order to set the link options.
-rw-r--r-- | src/core/devices/nm-device-bond.c | 44 | ||||
-rw-r--r-- | src/core/devices/nm-device.c | 3 | ||||
-rw-r--r-- | src/core/platform/nm-fake-platform.c | 26 | ||||
-rw-r--r-- | src/core/platform/tests/test-link.c | 17 | ||||
-rw-r--r-- | src/libnm-glib-aux/nm-shared-utils.h | 8 | ||||
-rw-r--r-- | src/libnm-platform/nm-linux-platform.c | 70 | ||||
-rw-r--r-- | src/libnm-platform/nm-platform.c | 83 | ||||
-rw-r--r-- | src/libnm-platform/nm-platform.h | 28 |
8 files changed, 233 insertions, 46 deletions
diff --git a/src/core/devices/nm-device-bond.c b/src/core/devices/nm-device-bond.c index 8e0cf33fe6..4b48db3344 100644 --- a/src/core/devices/nm-device-bond.c +++ b/src/core/devices/nm-device-bond.c @@ -229,24 +229,18 @@ controller_update_port_connection(NMDevice *self, NMConnection *connection, GError **error) { - NMSettingBondPort *s_port; - int ifindex_port = nm_device_get_ifindex(port); - NMConnection *applied_connection = nm_device_get_applied_connection(self); - uint queue_id = NM_BOND_PORT_QUEUE_ID_DEF; - gs_free char *queue_id_str = NULL; + NMSettingBondPort *s_port; + int ifindex_port = nm_device_get_ifindex(port); + NMConnection *applied_connection = nm_device_get_applied_connection(self); + const NMPlatformLink *pllink; g_return_val_if_fail(ifindex_port > 0, FALSE); s_port = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_BOND_PORT); + pllink = nm_platform_link_get(nm_device_get_platform(port), ifindex_port); - queue_id_str = - nm_platform_sysctl_slave_get_option(nm_device_get_platform(self), ifindex_port, "queue_id"); - if (queue_id_str) { - queue_id = - _nm_utils_ascii_str_to_int64(queue_id_str, 10, 0, 65535, NM_BOND_PORT_QUEUE_ID_DEF); - g_object_set(s_port, NM_SETTING_BOND_PORT_QUEUE_ID, queue_id, NULL); - } else - _LOGW(LOGD_BOND, "failed to read bond port setting '%s'", NM_SETTING_BOND_PORT_QUEUE_ID); + if (pllink && pllink->port_kind == NM_PORT_KIND_BOND) + g_object_set(s_port, NM_SETTING_BOND_PORT_QUEUE_ID, pllink->port_data.bond.queue_id, NULL); g_object_set(nm_connection_get_setting_connection(connection), NM_SETTING_CONNECTION_MASTER, @@ -637,23 +631,13 @@ act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) static void commit_port_options(NMDevice *bond_device, NMDevice *port, NMSettingBondPort *s_port) { - char queue_id_str[IFNAMSIZ + NM_STRLEN(":") + 5 + 100]; - - /* - * The queue-id of bond port is read only, we should modify bond interface using: - * echo "eth1:2" > /sys/class/net/bond0/bonding/queue_id - * Kernel allows parital editing, so no need to care about other bond ports. - */ - g_snprintf(queue_id_str, - sizeof(queue_id_str), - "%s:%" G_GUINT32_FORMAT, - nm_device_get_iface(port), - s_port ? nm_setting_bond_port_get_queue_id(s_port) : NM_BOND_PORT_QUEUE_ID_DEF); - - nm_platform_sysctl_master_set_option(nm_device_get_platform(bond_device), - nm_device_get_ifindex(bond_device), - "queue_id", - queue_id_str); + nm_platform_link_change( + nm_device_get_platform(port), + nm_device_get_ifindex(port), + NULL, + &((NMPlatformLinkBondPort){.queue_id = s_port ? nm_setting_bond_port_get_queue_id(s_port) + : NM_BOND_PORT_QUEUE_ID_DEF}), + 0); } static NMTernary diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index c7d9f9d89b..ed840044c5 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -2861,7 +2861,7 @@ nm_device_link_properties_set(NMDevice *self, gboolean reapply) _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)) { + if (nm_platform_link_change(platform, ifindex, &props, NULL, flags)) { _LOGD(LOGD_DEVICE, "link properties successfully set"); } else { _LOGW(LOGD_DEVICE, "failure setting link properties"); @@ -2888,6 +2888,7 @@ link_properties_reset(NMDevice *self) if (nm_platform_link_change(platform, ifindex, &priv->link_props_state.props, + NULL, priv->link_props_state.flags)) { _LOGD(LOGD_DEVICE, "link properties successfully reset"); } else { diff --git a/src/core/platform/nm-fake-platform.c b/src/core/platform/nm-fake-platform.c index 5a16148514..cd9c316902 100644 --- a/src/core/platform/nm-fake-platform.c +++ b/src/core/platform/nm-fake-platform.c @@ -701,6 +701,31 @@ link_supports_sriov(NMPlatform *platform, int ifindex) } static gboolean +link_change(NMPlatform *platform, + int ifindex, + NMPlatformLinkProps *props, + NMPortKind port_kind, + const NMPlatformLinkPortData *port_data, + NMPlatformLinkChangeFlags flags) +{ + NMFakePlatformLink *device = link_get(platform, ifindex); + nm_auto_nmpobj NMPObject *obj_tmp = NULL; + + switch (port_kind) { + case NM_PORT_KIND_BOND: + obj_tmp = nmp_object_clone(device->obj, FALSE); + obj_tmp->link.port_kind = NM_PORT_KIND_BOND; + obj_tmp->link.port_data.bond.queue_id = port_data->bond.queue_id; + link_set_obj(platform, device, obj_tmp); + return TRUE; + case NM_PORT_KIND_NONE: + return TRUE; + } + + return nm_assert_unreachable_val(TRUE); +} + +static gboolean link_enslave(NMPlatform *platform, int master, int slave) { NMFakePlatformLink *device = link_get(platform, slave); @@ -1394,6 +1419,7 @@ nm_fake_platform_class_init(NMFakePlatformClass *klass) platform_class->link_set_address = link_set_address; platform_class->link_set_mtu = link_set_mtu; + platform_class->link_change = link_change; platform_class->link_change_flags = link_change_flags; platform_class->link_get_driver_info = link_get_driver_info; diff --git a/src/core/platform/tests/test-link.c b/src/core/platform/tests/test-link.c index 1b5b800353..b7002e128c 100644 --- a/src/core/platform/tests/test-link.c +++ b/src/core/platform/tests/test-link.c @@ -273,6 +273,21 @@ test_slave(int master, int type, SignalData *master_changed) else g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, ifindex)); + if (NM_IN_SET(link_type, NM_LINK_TYPE_BOND)) { + const NMPlatformLink *link; + NMPlatformLinkBondPort bond_port; + + bond_port = (NMPlatformLinkBondPort){ + .queue_id = 5, + }; + g_assert(nm_platform_link_change(NM_PLATFORM_GET, ifindex, NULL, &bond_port, 0)); + accept_signals(link_changed, 1, 3); + + link = nmtstp_link_get(NM_PLATFORM_GET, ifindex, SLAVE_NAME); + g_assert(link); + g_assert_cmpint(link->port_data.bond.queue_id, ==, 5); + } + test_link_changed_signal_arg1 = FALSE; test_link_changed_signal_arg2 = FALSE; g_signal_connect(NM_PLATFORM_GET, @@ -2664,7 +2679,7 @@ test_link_set_properties(void) | NM_PLATFORM_LINK_CHANGE_GSO_MAX_SEGMENTS; ifindex = nmtstp_link_dummy_add(NM_PLATFORM_GET, FALSE, "dummy1")->ifindex; - g_assert(nm_platform_link_change(NM_PLATFORM_GET, ifindex, &props, flags)); + g_assert(nm_platform_link_change(NM_PLATFORM_GET, ifindex, &props, NULL, flags)); link = nmtstp_link_get(NM_PLATFORM_GET, ifindex, "dummy1"); g_assert(link); diff --git a/src/libnm-glib-aux/nm-shared-utils.h b/src/libnm-glib-aux/nm-shared-utils.h index 84ff6b6a1d..7233d77d40 100644 --- a/src/libnm-glib-aux/nm-shared-utils.h +++ b/src/libnm-glib-aux/nm-shared-utils.h @@ -93,6 +93,14 @@ G_STATIC_ASSERT(sizeof(int) == sizeof(gint32)); /*****************************************************************************/ +typedef enum _nm_packed { + /* No type, empty value */ + NM_PORT_KIND_NONE, + NM_PORT_KIND_BOND, +} NMPortKind; + +/*****************************************************************************/ + typedef enum { /* No type, used as error value */ diff --git a/src/libnm-platform/nm-linux-platform.c b/src/libnm-platform/nm-linux-platform.c index 4ca0948540..c51ccdebe9 100644 --- a/src/libnm-platform/nm-linux-platform.c +++ b/src/libnm-platform/nm-linux-platform.c @@ -3385,9 +3385,11 @@ _new_from_nl_link(NMPlatform *platform, if (tb[IFLA_LINKINFO]) { static const struct nla_policy policy_link_info[] = { - [IFLA_INFO_KIND] = {.type = NLA_STRING}, - [IFLA_INFO_DATA] = {.type = NLA_NESTED}, - [IFLA_INFO_XSTATS] = {.type = NLA_NESTED}, + [IFLA_INFO_KIND] = {.type = NLA_STRING}, + [IFLA_INFO_DATA] = {.type = NLA_NESTED}, + [IFLA_INFO_XSTATS] = {.type = NLA_NESTED}, + [IFLA_INFO_SLAVE_KIND] = {.type = NLA_STRING}, + [IFLA_INFO_SLAVE_DATA] = {.type = NLA_NESTED}, }; struct nlattr *li[G_N_ELEMENTS(policy_link_info)]; @@ -3398,6 +3400,33 @@ _new_from_nl_link(NMPlatform *platform, nl_info_kind = nla_get_string(li[IFLA_INFO_KIND]); nl_info_data = li[IFLA_INFO_DATA]; + + if (li[IFLA_INFO_SLAVE_KIND]) { + const char *s = nla_get_string(li[IFLA_INFO_SLAVE_KIND]); + + if (nm_streq(s, "bond")) + obj->link.port_kind = NM_PORT_KIND_BOND; + } + + if (li[IFLA_INFO_SLAVE_DATA]) { + static const struct nla_policy policy_bond_port[] = { + [IFLA_BOND_SLAVE_QUEUE_ID] = {.type = NLA_U16}, + }; + struct nlattr *bp[G_N_ELEMENTS(policy_bond_port)]; + + switch (obj->link.port_kind) { + case NM_PORT_KIND_BOND: + if (nla_parse_nested_arr(bp, li[IFLA_INFO_SLAVE_DATA], policy_bond_port) < 0) + return NULL; + + if (bp[IFLA_BOND_SLAVE_QUEUE_ID]) + obj->link.port_data.bond.queue_id = nla_get_u16(bp[IFLA_BOND_SLAVE_QUEUE_ID]); + + break; + case NM_PORT_KIND_NONE: + break; + } + } } if (tb[IFLA_TXQLEN]) @@ -8440,12 +8469,16 @@ link_delete(NMPlatform *platform, int ifindex) } static gboolean -link_change(NMPlatform *platform, - int ifindex, - NMPlatformLinkProps *props, - NMPlatformLinkChangeFlags flags) +link_change(NMPlatform *platform, + int ifindex, + NMPlatformLinkProps *props, + NMPortKind port_kind, + const NMPlatformLinkPortData *port_data, + NMPlatformLinkChangeFlags flags) { nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + struct nlattr *nl_info; + struct nlattr *nl_port_data; nlmsg = _nl_msg_new_link(RTM_NEWLINK, 0, ifindex, NULL); if (!nlmsg) @@ -8460,6 +8493,29 @@ link_change(NMPlatform *platform, if (flags & NM_PLATFORM_LINK_CHANGE_GRO_MAX_SIZE) NLA_PUT_U32(nlmsg, IFLA_GRO_MAX_SIZE, props->gro_max_size); + switch (port_kind) { + case NM_PORT_KIND_BOND: + + nm_assert(port_data); + + if (!(nl_info = nla_nest_start(nlmsg, IFLA_LINKINFO))) + goto nla_put_failure; + + nm_assert(nm_streq0("bond", nm_link_type_to_rtnl_type_string(NM_LINK_TYPE_BOND))); + NLA_PUT_STRING(nlmsg, IFLA_INFO_SLAVE_KIND, "bond"); + + if (!(nl_port_data = nla_nest_start(nlmsg, IFLA_INFO_SLAVE_DATA))) + goto nla_put_failure; + + NLA_PUT_U16(nlmsg, IFLA_BOND_SLAVE_QUEUE_ID, port_data->bond.queue_id); + + nla_nest_end(nlmsg, nl_port_data); + nla_nest_end(nlmsg, nl_info); + break; + case NM_PORT_KIND_NONE: + break; + } + return do_change_link(platform, CHANGE_LINK_TYPE_UNSPEC, ifindex, nlmsg, NULL) == 0; nla_put_failure: g_return_val_if_reached(FALSE); diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c index 779c5fba51..20ee23efb4 100644 --- a/src/libnm-platform/nm-platform.c +++ b/src/libnm-platform/nm-platform.c @@ -62,6 +62,31 @@ G_STATIC_ASSERT(sizeof(((NMPlatformLink *) NULL)->l_perm_address.data) == _NM_UT G_STATIC_ASSERT(sizeof(((NMPlatformLink *) NULL)->l_broadcast.data) == _NM_UTILS_HWADDR_LEN_MAX); static const char * +_nmp_link_port_data_to_string(NMPortKind port_kind, + const NMPlatformLinkPortData *port_data, + char *sbuf, + gsize sbuf_len) +{ + const char *sbuf0 = sbuf; + + nm_assert(port_data); + + switch (port_kind) { + case NM_PORT_KIND_NONE: + nm_strbuf_append_c(&sbuf, &sbuf_len, '\0'); + goto out; + case NM_PORT_KIND_BOND: + nm_strbuf_append(&sbuf, &sbuf_len, "port bond queue-id %u", port_data->bond.queue_id); + goto out; + } + + nm_strbuf_append(&sbuf, &sbuf_len, "invalid-port-type %d", (int) port_kind); + +out: + return sbuf0; +} + +static const char * _nmp_link_address_to_string(const NMPLinkAddress *addr, char buf[static(_NM_UTILS_HWADDR_LEN_MAX * 3)]) { @@ -2137,14 +2162,19 @@ gboolean nm_platform_link_change(NMPlatform *self, int ifindex, NMPlatformLinkProps *props, + NMPlatformLinkBondPort *bond_port, NMPlatformLinkChangeFlags flags) { _CHECK_SELF(self, klass, FALSE); g_return_val_if_fail(ifindex >= 0, FALSE); - if (flags == 0) - return TRUE; + nm_assert(!NM_FLAGS_ANY(flags, + NM_PLATFORM_LINK_CHANGE_TX_QUEUE_LENGTH + | NM_PLATFORM_LINK_CHANGE_GSO_MAX_SIZE + | NM_PLATFORM_LINK_CHANGE_GSO_MAX_SEGMENTS + | NM_PLATFORM_LINK_CHANGE_GRO_MAX_SIZE) + || props); if (_LOGD_ENABLED()) { nm_auto_free_gstring GString *str = g_string_new(""); @@ -2157,6 +2187,8 @@ nm_platform_link_change(NMPlatform *self, 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 (bond_port) + g_string_append_printf(str, "bond-port queue-id %d", bond_port->queue_id); if (str->len > 0 && str->str[str->len - 1] == ' ') g_string_truncate(str, str->len - 1); @@ -2164,7 +2196,12 @@ nm_platform_link_change(NMPlatform *self, _LOG3D("link: change: %s", str->str); } - return klass->link_change(self, ifindex, props, flags); + return klass->link_change(self, + ifindex, + props, + bond_port ? NM_PORT_KIND_BOND : NM_PORT_KIND_NONE, + (const NMPlatformLinkPortData *) bond_port, + flags); } /** @@ -5851,6 +5888,7 @@ nm_platform_link_to_string(const NMPlatformLink *link, char *buf, gsize len) char *s; gsize l; char str_addrmode[30]; + char str_port_data[200]; char str_address[_NM_UTILS_HWADDR_LEN_MAX * 3]; char str_perm_address[_NM_UTILS_HWADDR_LEN_MAX * 3]; char str_broadcast[_NM_UTILS_HWADDR_LEN_MAX * 3]; @@ -5894,6 +5932,11 @@ nm_platform_link_to_string(const NMPlatformLink *link, char *buf, gsize len) _nmp_link_address_to_string(&link->l_perm_address, str_perm_address); _nmp_link_address_to_string(&link->l_broadcast, str_broadcast); + _nmp_link_port_data_to_string(link->port_kind, + &link->port_data, + str_port_data, + sizeof(str_port_data)); + str_link_type = nm_link_type_to_string(link->type); g_snprintf( @@ -5915,6 +5958,7 @@ nm_platform_link_to_string(const NMPlatformLink *link, char *buf, gsize len) "%s%s" /* l_broadcast */ "%s%s" /* inet6_token */ "%s%s" /* driver */ + "%s%s" /* port_data */ " tx-queue-len %u" " gso-max-size %u" " gso-max-segs %u" @@ -5951,6 +5995,7 @@ nm_platform_link_to_string(const NMPlatformLink *link, char *buf, gsize len) : "", link->driver ? " driver " : "", link->driver ?: "", + NM_PRINT_FMT_QUOTED2(str_port_data[0] != '\0', " ", str_port_data, ""), link->link_props.tx_queue_length, link->link_props.gso_max_size, link->link_props.gso_max_segments, @@ -7806,6 +7851,7 @@ nm_platform_link_hash_update(const NMPlatformLink *obj, NMHashState *h) obj->link_props.gso_max_size, obj->link_props.gso_max_segments, obj->link_props.gro_max_size, + obj->port_kind, obj->rx_packets, obj->rx_bytes, obj->tx_packets, @@ -7824,6 +7870,20 @@ nm_platform_link_hash_update(const NMPlatformLink *obj, NMHashState *h) nm_hash_update_mem(h, obj->l_broadcast.data, NM_MIN(obj->l_broadcast.len, sizeof(obj->l_broadcast.data))); + + switch (obj->port_kind) { + case NM_PORT_KIND_NONE: + break; + case NM_PORT_KIND_BOND: + nm_platform_link_bond_port_hash_update(&obj->port_data.bond, h); + break; + } +} + +void +nm_platform_link_bond_port_hash_update(const NMPlatformLinkBondPort *obj, NMHashState *h) +{ + nm_hash_update_vals(h, obj->queue_id); } int @@ -7857,6 +7917,14 @@ nm_platform_link_cmp(const NMPlatformLink *a, const NMPlatformLink *b) 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, port_kind); + switch (a->port_kind) { + case NM_PORT_KIND_NONE: + break; + case NM_PORT_KIND_BOND: + NM_CMP_RETURN(nm_platform_link_bond_port_cmp(&a->port_data.bond, &b->port_data.bond)); + break; + } NM_CMP_FIELD(a, b, rx_packets); NM_CMP_FIELD(a, b, rx_bytes); NM_CMP_FIELD(a, b, tx_packets); @@ -7942,6 +8010,15 @@ nm_platform_lnk_bond_hash_update(const NMPlatformLnkBond *obj, NMHashState *h) } int +nm_platform_link_bond_port_cmp(const NMPlatformLinkBondPort *a, const NMPlatformLinkBondPort *b) +{ + NM_CMP_SELF(a, b); + NM_CMP_FIELD(a, b, queue_id); + + return 0; +} + +int nm_platform_lnk_bond_cmp(const NMPlatformLnkBond *a, const NMPlatformLnkBond *b) { NM_CMP_SELF(a, b); diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h index 1fe0b3cbe7..e850cde392 100644 --- a/src/libnm-platform/nm-platform.h +++ b/src/libnm-platform/nm-platform.h @@ -169,6 +169,14 @@ struct _NMPlatformObjWithIfindex { __NMPlatformObjWithIfindex_COMMON; } _nm_alignas(NMPlatformObject); +typedef struct { + guint16 queue_id; +} NMPlatformLinkBondPort; + +typedef union { + NMPlatformLinkBondPort bond; +} NMPlatformLinkPortData; + struct _NMPlatformLink { __NMPlatformObjWithIfindex_COMMON; char name[NMP_IFNAMSIZ]; @@ -221,6 +229,12 @@ struct _NMPlatformLink { NMPlatformLinkProps link_props; + /* IFLA_INFO_SLAVE_KIND */ + NMPortKind port_kind; + + /* an interface can only hold IFLA_INFO_SLAVE_DATA for one link type */ + NMPlatformLinkPortData port_data; + /* @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; @@ -1112,10 +1126,12 @@ typedef struct { NMLinkType type, int ifindex, gconstpointer extra_data); - gboolean (*link_change)(NMPlatform *self, - int ifindex, - NMPlatformLinkProps *props, - NMPlatformLinkChangeFlags flags); + gboolean (*link_change)(NMPlatform *self, + int ifindex, + NMPlatformLinkProps *props, + NMPortKind port_kind, + const NMPlatformLinkPortData *port_data, + 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); @@ -1955,6 +1971,7 @@ nm_platform_link_change_flags(NMPlatform *self, int ifindex, unsigned value, gbo gboolean nm_platform_link_change(NMPlatform *self, int ifindex, NMPlatformLinkProps *props, + NMPlatformLinkBondPort *bond_port, NMPlatformLinkChangeFlags flags); gboolean nm_platform_link_get_udev_property(NMPlatform *self, @@ -2455,6 +2472,9 @@ int nm_platform_tfilter_cmp(const NMPlatformTfilter *a, const NMPlatformTfilter int nm_platform_mptcp_addr_cmp(const NMPlatformMptcpAddr *a, const NMPlatformMptcpAddr *b); void nm_platform_link_hash_update(const NMPlatformLink *obj, NMHashState *h); +void nm_platform_link_bond_port_hash_update(const NMPlatformLinkBondPort *obj, NMHashState *h); +int nm_platform_link_bond_port_cmp(const NMPlatformLinkBondPort *a, + const NMPlatformLinkBondPort *b); void nm_platform_ip4_route_hash_update(const NMPlatformIP4Route *obj, NMPlatformIPRouteCmpType cmp_type, NMHashState *h); |