diff options
Diffstat (limited to 'src/libnm-platform')
| -rw-r--r-- | src/libnm-platform/nm-linux-platform.c | 148 | ||||
| -rw-r--r-- | src/libnm-platform/nm-platform-utils.c | 128 | ||||
| -rw-r--r-- | src/libnm-platform/nm-platform-utils.h | 8 | ||||
| -rw-r--r-- | src/libnm-platform/nm-platform.c | 376 | ||||
| -rw-r--r-- | src/libnm-platform/nm-platform.h | 110 | ||||
| -rw-r--r-- | src/libnm-platform/nmp-base.h | 16 | ||||
| -rw-r--r-- | src/libnm-platform/nmp-object.c | 12 | ||||
| -rw-r--r-- | src/libnm-platform/nmp-object.h | 8 | ||||
| -rw-r--r-- | src/libnm-platform/nmp-plobj.c | 4 | ||||
| -rw-r--r-- | src/libnm-platform/nmp-plobj.h | 2 | ||||
| -rw-r--r-- | src/libnm-platform/wifi/nm-wifi-utils-nl80211.c | 113 | ||||
| -rw-r--r-- | src/libnm-platform/wifi/nm-wifi-utils-private.h | 5 | ||||
| -rw-r--r-- | src/libnm-platform/wifi/nm-wifi-utils-wext.c | 16 | ||||
| -rw-r--r-- | src/libnm-platform/wifi/nm-wifi-utils.c | 22 | ||||
| -rw-r--r-- | src/libnm-platform/wifi/nm-wifi-utils.h | 6 |
15 files changed, 672 insertions, 302 deletions
diff --git a/src/libnm-platform/nm-linux-platform.c b/src/libnm-platform/nm-linux-platform.c index 99eab9c7..22cd5784 100644 --- a/src/libnm-platform/nm-linux-platform.c +++ b/src/libnm-platform/nm-linux-platform.c @@ -163,7 +163,7 @@ typedef enum _nm_packed { G_STATIC_ASSERT(RTA_MAX == (__RTA_MAX - 1)); #define RTA_PREF 20 #undef RTA_MAX -#define RTA_MAX (MAX((__RTA_MAX - 1), RTA_PREF)) +#define RTA_MAX (NM_MAX_CONST((__RTA_MAX - 1), RTA_PREF)) #ifndef MACVLAN_FLAG_NOPROMISC #define MACVLAN_FLAG_NOPROMISC 1 @@ -229,6 +229,18 @@ G_STATIC_ASSERT(RTA_MAX == (__RTA_MAX - 1)); /*****************************************************************************/ +#define IFLA_HSR_UNSPEC 0 +#define IFLA_HSR_PORT1 1 +#define IFLA_HSR_PORT2 2 +#define IFLA_HSR_MULTICAST_SPEC 3 +#define IFLA_HSR_SUPERVISION_ADDR 4 +#define IFLA_HSR_SEQ_NR 5 +#define IFLA_HSR_VERSION 6 +#define IFLA_HSR_PROTOCOL 7 +#define __IFLA_HSR_MAX 8 + +/*****************************************************************************/ + #define IFLA_VTI_UNSPEC 0 #define IFLA_VTI_LINK 1 #define IFLA_VTI_IKEY 2 @@ -847,6 +859,7 @@ static const LinkDesc link_descs[] = { [NM_LINK_TYPE_BRIDGE] = {"bridge", "bridge", "bridge"}, [NM_LINK_TYPE_BOND] = {"bond", "bond", "bond"}, + [NM_LINK_TYPE_HSR] = {"hsr", "hsr", "hsr"}, [NM_LINK_TYPE_TEAM] = {"team", "team", NULL}, }; @@ -869,6 +882,7 @@ _link_type_from_rtnl_type(const char *name) NM_LINK_TYPE_DUMMY, /* "dummy" */ NM_LINK_TYPE_GRE, /* "gre" */ NM_LINK_TYPE_GRETAP, /* "gretap" */ + NM_LINK_TYPE_HSR, /* "hsr" */ NM_LINK_TYPE_IFB, /* "ifb" */ NM_LINK_TYPE_IP6GRE, /* "ip6gre" */ NM_LINK_TYPE_IP6GRETAP, /* "ip6gretap" */ @@ -943,6 +957,7 @@ _link_type_from_devtype(const char *name) NM_LINK_TYPE_BNEP, /* "bluetooth" */ NM_LINK_TYPE_BOND, /* "bond" */ NM_LINK_TYPE_BRIDGE, /* "bridge" */ + NM_LINK_TYPE_HSR, /* "hsr" */ NM_LINK_TYPE_PPP, /* "ppp" */ NM_LINK_TYPE_VLAN, /* "vlan" */ NM_LINK_TYPE_VRF, /* "vrf" */ @@ -1096,7 +1111,7 @@ _addrtime_extend_lifetime(guint32 lifetime, guint32 seconds) return lifetime; v = (guint64) lifetime + (guint64) seconds; - return MIN(v, NM_PLATFORM_LIFETIME_PERMANENT - 1); + return NM_MIN(v, NM_PLATFORM_LIFETIME_PERMANENT - 1); } /* The rtnl_addr object contains relative lifetimes @valid and @preferred @@ -1805,6 +1820,51 @@ _parse_lnk_gre(const char *kind, struct nlattr *info_data) /*****************************************************************************/ +static NMPObject * +_parse_lnk_hsr(const char *kind, struct nlattr *info_data) +{ + static const struct nla_policy policy[] = { + [IFLA_HSR_PORT1] = {.type = NLA_U32}, + [IFLA_HSR_PORT2] = {.type = NLA_U32}, + [IFLA_HSR_MULTICAST_SPEC] = {.type = NLA_U8}, + [IFLA_HSR_SUPERVISION_ADDR] = {.minlen = sizeof(NMEtherAddr)}, + [IFLA_HSR_PROTOCOL] = {.type = NLA_U8}, + }; + NMPlatformLnkHsr *props; + struct nlattr *tb[G_N_ELEMENTS(policy)]; + NMPObject *obj; + guint32 v_u32; + + if (!info_data || !kind) + return NULL; + + if (nla_parse_nested_arr(tb, info_data, policy) < 0) + return NULL; + + obj = nmp_object_new(NMP_OBJECT_TYPE_LNK_HSR, NULL); + props = &obj->lnk_hsr; + if (tb[IFLA_HSR_PORT1]) { + v_u32 = nla_get_u32(tb[IFLA_HSR_PORT1]); + if (v_u32 <= (unsigned) G_MAXINT) + props->port1 = v_u32; + } + if (tb[IFLA_HSR_PORT2]) { + v_u32 = nla_get_u32(tb[IFLA_HSR_PORT2]); + if (v_u32 <= (unsigned) G_MAXINT) + props->port2 = v_u32; + } + if (tb[IFLA_HSR_MULTICAST_SPEC]) + props->multicast_spec = nla_get_u8(tb[IFLA_HSR_MULTICAST_SPEC]); + if (tb[IFLA_HSR_SUPERVISION_ADDR]) + nla_memcpy(&props->supervision_address, tb[IFLA_HSR_SUPERVISION_ADDR], sizeof(NMEtherAddr)); + if (tb[IFLA_HSR_PROTOCOL]) + props->prp = nla_get_u8(tb[IFLA_HSR_PROTOCOL]); + + return obj; +} + +/*****************************************************************************/ + /* IFLA_IPOIB_* were introduced in the 3.7 kernel, but the kernel headers * we're building against might not have those properties even though the * running kernel might. @@ -3408,6 +3468,8 @@ _new_from_nl_link(NMPlatform *platform, if (nm_streq(s, "bond")) obj->link.port_kind = NM_PORT_KIND_BOND; + else if (nm_streq(s, "bridge")) + obj->link.port_kind = NM_PORT_KIND_BRIDGE; } if (li[IFLA_INFO_SLAVE_DATA]) { @@ -3415,7 +3477,13 @@ _new_from_nl_link(NMPlatform *platform, [IFLA_BOND_SLAVE_QUEUE_ID] = {.type = NLA_U16}, [IFLA_BOND_SLAVE_PRIO] = {.type = NLA_S32}, }; - struct nlattr *bp[G_N_ELEMENTS(policy_bond_port)]; + struct nlattr *bp[G_N_ELEMENTS(policy_bond_port)]; + static const struct nla_policy policy_bridge_port[] = { + [IFLA_BRPORT_COST] = {.type = NLA_U32}, + [IFLA_BRPORT_PRIORITY] = {.type = NLA_U16}, + [IFLA_BRPORT_MODE] = {.type = NLA_U8}, + }; + struct nlattr *brp[G_N_ELEMENTS(policy_bridge_port)]; switch (obj->link.port_kind) { case NM_PORT_KIND_BOND: @@ -3441,6 +3509,19 @@ _new_from_nl_link(NMPlatform *platform, } } break; + case NM_PORT_KIND_BRIDGE: + if (nla_parse_nested_arr(brp, li[IFLA_INFO_SLAVE_DATA], policy_bridge_port) < 0) + return NULL; + + if (brp[IFLA_BRPORT_COST]) + obj->link.port_data.bridge.path_cost = nla_get_u32(brp[IFLA_BRPORT_COST]); + + if (brp[IFLA_BRPORT_PRIORITY]) + obj->link.port_data.bridge.priority = nla_get_u16(brp[IFLA_BRPORT_PRIORITY]); + + if (brp[IFLA_BRPORT_MODE]) + obj->link.port_data.bridge.hairpin = nla_get_u8(brp[IFLA_BRPORT_MODE]); + break; case NM_PORT_KIND_NONE: break; } @@ -3547,6 +3628,9 @@ _new_from_nl_link(NMPlatform *platform, case NM_LINK_TYPE_GRETAP: lnk_data = _parse_lnk_gre(nl_info_kind, nl_info_data); break; + case NM_LINK_TYPE_HSR: + lnk_data = _parse_lnk_hsr(nl_info_kind, nl_info_data); + break; case NM_LINK_TYPE_INFINIBAND: lnk_data = _parse_lnk_infiniband(nl_info_kind, nl_info_data); break; @@ -3922,7 +4006,7 @@ _new_from_nl_route(const struct nlmsghdr *nlh, gboolean id_only, ParseNlmsgIter * hops in this list). */ nm_assert(v4_n_nexthops > 0u); if (v4_n_nexthops - 1u >= v4_nh_extra_alloc) { - v4_nh_extra_alloc = NM_MAX(4, v4_nh_extra_alloc * 2u); + v4_nh_extra_alloc = NM_MAX(4u, v4_nh_extra_alloc * 2u); if (!v4_nh_extra_nexthops_heap) { v4_nh_extra_nexthops_heap = g_new(NMPlatformIP4RtNextHop, v4_nh_extra_alloc); @@ -4977,6 +5061,24 @@ _nl_msg_new_link_set_linkinfo(struct nl_msg *msg, NMLinkType link_type, gconstpo NLA_PUT_U16(msg, IFLA_GRE_OFLAGS, htons(props->output_flags)); break; } + case NM_LINK_TYPE_HSR: + { + const NMPlatformLnkHsr *props = extra_data; + + nm_assert(props); + + if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) + goto nla_put_failure; + + NLA_PUT_U32(msg, IFLA_HSR_PORT1, props->port1); + NLA_PUT_U32(msg, IFLA_HSR_PORT2, props->port2); + + if (props->multicast_spec) + NLA_PUT_U8(msg, IFLA_HSR_MULTICAST_SPEC, props->multicast_spec); + + NLA_PUT_U8(msg, IFLA_HSR_PROTOCOL, props->prp); + break; + } case NM_LINK_TYPE_SIT: { const NMPlatformLnkSit *props = extra_data; @@ -8533,6 +8635,26 @@ link_change(NMPlatform *platform, nla_nest_end(nlmsg, nl_port_data); nla_nest_end(nlmsg, nl_info); break; + case NM_PORT_KIND_BRIDGE: + + nm_assert(port_data); + + if (!(nl_info = nla_nest_start(nlmsg, IFLA_LINKINFO))) + goto nla_put_failure; + + nm_assert(nm_streq0("bridge", nm_link_type_to_rtnl_type_string(NM_LINK_TYPE_BRIDGE))); + NLA_PUT_STRING(nlmsg, IFLA_INFO_SLAVE_KIND, "bridge"); + + if (!(nl_port_data = nla_nest_start(nlmsg, IFLA_INFO_SLAVE_DATA))) + goto nla_put_failure; + + NLA_PUT_U32(nlmsg, IFLA_BRPORT_COST, port_data->bridge.path_cost); + NLA_PUT_U16(nlmsg, IFLA_BRPORT_PRIORITY, port_data->bridge.priority); + NLA_PUT_U8(nlmsg, IFLA_BRPORT_MODE, port_data->bridge.hairpin); + + nla_nest_end(nlmsg, nl_port_data); + nla_nest_end(nlmsg, nl_info); + break; case NM_PORT_KIND_NONE: break; } @@ -9551,22 +9673,6 @@ wifi_set_wake_on_wlan(NMPlatform *platform, int ifindex, _NMSettingWirelessWakeO return nm_wifi_utils_set_wake_on_wlan(wifi_data, wowl); } -static gboolean -wifi_get_csme_conn_info(NMPlatform *platform, int ifindex, NMPlatformCsmeConnInfo *out_conn_info) -{ - WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, FALSE); - - return nm_wifi_utils_get_csme_conn_info(wifi_data, out_conn_info); -} - -static gboolean -wifi_get_device_from_csme(NMPlatform *platform, int ifindex) -{ - WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, FALSE); - - return nm_wifi_utils_get_device_from_csme(wifi_data); -} - /*****************************************************************************/ static gboolean @@ -11446,8 +11552,6 @@ nm_linux_platform_class_init(NMLinuxPlatformClass *klass) platform_class->wifi_indicate_addressing_running = wifi_indicate_addressing_running; platform_class->wifi_get_wake_on_wlan = wifi_get_wake_on_wlan; platform_class->wifi_set_wake_on_wlan = wifi_set_wake_on_wlan; - platform_class->wifi_get_csme_conn_info = wifi_get_csme_conn_info; - platform_class->wifi_get_device_from_csme = wifi_get_device_from_csme; platform_class->mesh_get_channel = mesh_get_channel; platform_class->mesh_set_channel = mesh_set_channel; diff --git a/src/libnm-platform/nm-platform-utils.c b/src/libnm-platform/nm-platform-utils.c index 08d82fe8..6074c342 100644 --- a/src/libnm-platform/nm-platform-utils.c +++ b/src/libnm-platform/nm-platform-utils.c @@ -554,7 +554,7 @@ _ASSERT_ethtool_feature_infos(void) for (k = 0; k < inf->n_kernel_names; k++) { const char *name = inf->kernel_names[k]; - g_assert(nm_strv_find_first(inf->kernel_names, k, name) < 0); + g_assert(!nm_strv_contains(inf->kernel_names, k, name)); /* these offload features are only informational and cannot be set from user-space * (NETIF_F_NEVER_CHANGE). We should not track them in _ethtool_feature_infos. */ @@ -1068,6 +1068,69 @@ nmp_utils_ethtool_set_ring(int ifindex, const NMEthtoolRingState *ring) } gboolean +nmp_utils_ethtool_get_channels(int ifindex, NMEthtoolChannelsState *channels) +{ + struct ethtool_channels eth_data; + + g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail(channels, FALSE); + + eth_data.cmd = ETHTOOL_GCHANNELS; + + if (_ethtool_call_once(ifindex, ð_data, sizeof(eth_data)) < 0) { + nm_log_trace(LOGD_PLATFORM, + "ethtool[%d]: %s: failure getting channels settings", + ifindex, + "get-channels"); + return FALSE; + } + + *channels = (NMEthtoolChannelsState){ + .rx = eth_data.rx_count, + .tx = eth_data.tx_count, + .other = eth_data.other_count, + .combined = eth_data.combined_count, + }; + + nm_log_trace(LOGD_PLATFORM, + "ethtool[%d]: %s: retrieved kernel channels settings", + ifindex, + "get-channels"); + return TRUE; +} + +gboolean +nmp_utils_ethtool_set_channels(int ifindex, const NMEthtoolChannelsState *channels) +{ + struct ethtool_channels eth_data; + + g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail(channels, FALSE); + + eth_data = (struct ethtool_channels){ + .cmd = ETHTOOL_SCHANNELS, + .rx_count = channels->rx, + .tx_count = channels->tx, + .other_count = channels->other, + .combined_count = channels->combined, + }; + + if (_ethtool_call_once(ifindex, ð_data, sizeof(eth_data)) < 0) { + nm_log_trace(LOGD_PLATFORM, + "ethtool[%d]: %s: failure setting channels settings", + ifindex, + "set-channels"); + return FALSE; + } + + nm_log_trace(LOGD_PLATFORM, + "ethtool[%d]: %s: set kernel channels settings", + ifindex, + "set-channels"); + return TRUE; +} + +gboolean nmp_utils_ethtool_get_pause(int ifindex, NMEthtoolPauseState *pause) { struct ethtool_pauseparam eth_data; @@ -1099,6 +1162,35 @@ nmp_utils_ethtool_get_pause(int ifindex, NMEthtoolPauseState *pause) } gboolean +nmp_utils_ethtool_get_eee(int ifindex, NMEthtoolEEEState *eee) +{ + struct ethtool_eee eth_data; + nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex); + + g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail(eee, FALSE); + + eth_data.cmd = ETHTOOL_GEEE; + if (_ethtool_call_handle(&shandle, ð_data, sizeof(struct ethtool_eee)) != 0) { + nm_log_trace(LOGD_PLATFORM, + "ethtool[%d]: %s: failure getting eee settings", + ifindex, + "get-eee"); + return FALSE; + } + + *eee = (NMEthtoolEEEState){ + .enabled = eth_data.eee_enabled == 1, + }; + + nm_log_trace(LOGD_PLATFORM, + "ethtool[%d]: %s: retrieved kernel eee settings", + ifindex, + "get-eee"); + return TRUE; +} + +gboolean nmp_utils_ethtool_set_pause(int ifindex, const NMEthtoolPauseState *pause) { struct ethtool_pauseparam eth_data; @@ -1125,6 +1217,36 @@ nmp_utils_ethtool_set_pause(int ifindex, const NMEthtoolPauseState *pause) return TRUE; } +gboolean +nmp_utils_ethtool_set_eee(int ifindex, const NMEthtoolEEEState *eee) +{ + struct ethtool_eee eth_data; + nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex); + + g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail(eee, FALSE); + + eth_data.cmd = ETHTOOL_GEEE; + if (_ethtool_call_handle(&shandle, ð_data, sizeof(struct ethtool_eee)) != 0) { + nm_log_trace(LOGD_PLATFORM, + "ethtool[%d]: %s: failure getting eee settings", + ifindex, + "get-eee"); + return FALSE; + } + + eth_data.cmd = ETHTOOL_SEEE, eth_data.eee_enabled = eee->enabled ? 1 : 0; + + if (_ethtool_call_handle(&shandle, ð_data, sizeof(struct ethtool_eee)) != 0) { + nm_log_trace(LOGD_PLATFORM, + "ethtool[%d]: %s: failure setting eee settings", + ifindex, + "set-eee"); + return FALSE; + } + nm_log_trace(LOGD_PLATFORM, "ethtool[%d]: %s: set kernel eee settings", ifindex, "set-eee"); + return TRUE; +} /*****************************************************************************/ gboolean @@ -2055,7 +2177,7 @@ nmp_utils_new_vlan_name(const char *parent_iface, guint32 vlan_id) ifname = g_new(char, IFNAMSIZ); parent_len = strlen(parent_iface); - parent_len = MIN(parent_len, IFNAMSIZ - 1 - id_len); + parent_len = NM_MIN(parent_len, IFNAMSIZ - 1 - id_len); memcpy(ifname, parent_iface, parent_len); g_snprintf(&ifname[parent_len], IFNAMSIZ - parent_len, ".%u", vlan_id); @@ -2134,7 +2256,7 @@ nmp_utils_lifetime_get(guint32 timestamp, t_preferred = nmp_utils_lifetime_rebase_relative_time_on_now(timestamp, preferred, now); - NM_SET_OUT(out_preferred, MIN(t_preferred, t_lifetime)); + NM_SET_OUT(out_preferred, NM_MIN(t_preferred, t_lifetime)); /* Assert that non-permanent addresses have a (positive) @timestamp. nmp_utils_lifetime_rebase_relative_time_on_now() * treats addresses with timestamp 0 as *now*. Addresses passed to _address_get_lifetime() always diff --git a/src/libnm-platform/nm-platform-utils.h b/src/libnm-platform/nm-platform-utils.h index 14b09a79..18fc6155 100644 --- a/src/libnm-platform/nm-platform-utils.h +++ b/src/libnm-platform/nm-platform-utils.h @@ -54,10 +54,18 @@ gboolean nmp_utils_ethtool_get_ring(int ifindex, NMEthtoolRingState *ring); gboolean nmp_utils_ethtool_set_ring(int ifindex, const NMEthtoolRingState *ring); +gboolean nmp_utils_ethtool_get_channels(int ifindex, NMEthtoolChannelsState *channels); + +gboolean nmp_utils_ethtool_set_channels(int ifindex, const NMEthtoolChannelsState *channels); + gboolean nmp_utils_ethtool_get_pause(int ifindex, NMEthtoolPauseState *pause); gboolean nmp_utils_ethtool_set_pause(int ifindex, const NMEthtoolPauseState *pause); +gboolean nmp_utils_ethtool_get_eee(int ifindex, NMEthtoolEEEState *eee); + +gboolean nmp_utils_ethtool_set_eee(int ifindex, const NMEthtoolEEEState *eee); + /*****************************************************************************/ gboolean nmp_utils_mii_supports_carrier_detect(int ifindex); diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c index 041354cf..531c98e8 100644 --- a/src/libnm-platform/nm-platform.c +++ b/src/libnm-platform/nm-platform.c @@ -88,6 +88,14 @@ _nmp_link_port_data_to_string(NMPortKind port_kind, port_data->bond.prio) : ""); goto out; + case NM_PORT_KIND_BRIDGE: + nm_strbuf_append(&sbuf, + &sbuf_len, + "port bridge path_cost %u priority %u hairpin %s", + port_data->bridge.path_cost, + port_data->bridge.priority, + port_data->bridge.hairpin ? "true" : "false"); + goto out; } nm_strbuf_append(&sbuf, &sbuf_len, "invalid-port-type %d", (int) port_kind); @@ -719,7 +727,7 @@ nm_platform_sysctl_ip_neigh_set_ipv6_reachable_time(NMPlatform *self, /* RFC 4861 says the value can't be greater than one hour. * Also use a reasonable lower threshold. */ - clamped = NM_CLAMP(value_ms, 100, 3600000); + clamped = NM_CLAMP(value_ms, 100u, 3600000u); nm_sprintf_buf(path, "/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", iface); nm_sprintf_buf(str, "%u", clamped); if (!nm_platform_sysctl_set(self, NMP_SYSCTL_PATHID_ABSOLUTE(path), str)) @@ -746,7 +754,7 @@ nm_platform_sysctl_ip_neigh_set_ipv6_retrans_time(NMPlatform *self, return TRUE; nm_sprintf_buf(path, "/proc/sys/net/ipv6/neigh/%s/retrans_time_ms", iface); - nm_sprintf_buf(str, "%u", NM_CLAMP(value_ms, 10, 3600000)); + nm_sprintf_buf(str, "%u", NM_CLAMP(value_ms, 10u, 3600000u)); return nm_platform_sysctl_set(self, NMP_SYSCTL_PATHID_ABSOLUTE(path), str); } @@ -983,7 +991,7 @@ nm_platform_sysctl_ip_conf_get_rp_filter_ipv4(NMPlatform *self, /*****************************************************************************/ static int -_link_get_all_presort(gconstpointer p_a, gconstpointer p_b, gpointer sort_by_name) +_link_get_all_presort(gconstpointer p_a, gconstpointer p_b) { const NMPlatformLink *a = NMP_OBJECT_CAST_LINK(*((const NMPObject **) p_a)); const NMPlatformLink *b = NMP_OBJECT_CAST_LINK(*((const NMPObject **) p_b)); @@ -994,28 +1002,30 @@ _link_get_all_presort(gconstpointer p_a, gconstpointer p_b, gpointer sort_by_nam if (b->ifindex == NM_LOOPBACK_IFINDEX) return 1; - if (GPOINTER_TO_INT(sort_by_name)) { - /* Initialized links first */ - if (a->initialized > b->initialized) - return -1; - if (a->initialized < b->initialized) - return 1; + /* Initialized links first */ + if (a->initialized > b->initialized) + return -1; + if (a->initialized < b->initialized) + return 1; - return strcmp(a->name, b->name); - } else - return a->ifindex - b->ifindex; + NM_CMP_DIRECT_STRCMP(a->name, b->name); + /* Fallback to ifindex */ + NM_CMP_DIRECT(a->ifindex, b->ifindex); + /* Fallback to pointer comparison */ + NM_CMP_DIRECT_PTR(a, b); + + return 0; } /** * nm_platform_link_get_all: * @self: platform instance - * @sort_by_name: whether to sort by name or ifindex. * * Retrieve a snapshot of configuration for all links at once. The result is * owned by the caller and should be freed with g_ptr_array_unref(). */ GPtrArray * -nm_platform_link_get_all(NMPlatform *self, gboolean sort_by_name) +nm_platform_link_get_all(NMPlatform *self) { gs_unref_ptrarray GPtrArray *links = NULL; GPtrArray *result; @@ -1041,9 +1051,9 @@ nm_platform_link_get_all(NMPlatform *self, gboolean sort_by_name) if (links->len == 0) return NULL; - /* first sort the links by their ifindex or name. Below we will sort + /* first sort the links by their name. Below we will sort * further by moving children/slaves to the end. */ - g_ptr_array_sort_with_data(links, _link_get_all_presort, GINT_TO_POINTER(sort_by_name)); + g_ptr_array_sort(links, _link_get_all_presort); unseen = g_hash_table_new(nm_direct_hash, NULL); for (i = 0; i < links->len; i++) { @@ -1383,6 +1393,12 @@ nm_platform_link_add(NMPlatform *self, buf_p, buf_len); break; + case NM_LINK_TYPE_HSR: + nm_strbuf_append_str(&buf_p, &buf_len, ", "); + nm_platform_lnk_hsr_to_string((const NMPlatformLnkHsr *) extra_data, + buf_p, + buf_len); + break; case NM_LINK_TYPE_IP6TNL: case NM_LINK_TYPE_IP6GRE: case NM_LINK_TYPE_IP6GRETAP: @@ -1628,7 +1644,7 @@ nm_platform_link_get_udev_property(NMPlatform *self, const char *name, const char **out_value) { - struct udev_device *udevice = NULL; + struct udev_device *udevice; const char *uproperty; udevice = nm_platform_link_get_udev_device(self, ifindex); @@ -1647,22 +1663,34 @@ nm_platform_link_get_udev_property(NMPlatform *self, * nm_platform_link_get_unmanaged: * @self: platform instance * @ifindex: interface index - * @unmanaged: management status (in case %TRUE is returned) * - * Returns: %TRUE if platform overrides NM default-unmanaged status, - * %FALSE otherwise (with @unmanaged unmodified). + * Returns: %NM_OPTION_BOOL_DEFAULT if the udev property NM_UNMANAGED + * is not set. Otherwise, return NM_UNMANAGED as boolean. */ -gboolean -nm_platform_link_get_unmanaged(NMPlatform *self, int ifindex, gboolean *unmanaged) +NMOptionBool +nm_platform_link_get_unmanaged(NMPlatform *self, int ifindex) { - const char *value; + struct udev_device *udevice; + const char *val; - if (nm_platform_link_get_udev_property(self, ifindex, "NM_UNMANAGED", &value)) { - NM_SET_OUT(unmanaged, _nm_utils_ascii_str_to_bool(value, FALSE)); - return TRUE; + udevice = nm_platform_link_get_udev_device(self, ifindex); + if (!udevice) + return NM_OPTION_BOOL_DEFAULT; + + val = udev_device_get_property_value(udevice, "NM_UNMANAGED"); + if (val) + return _nm_utils_ascii_str_to_bool(val, FALSE); + + val = udev_device_get_property_value(udevice, "ID_NET_MANAGED_BY"); + if (val) { + if (!nm_streq(val, "org.freedesktop.NetworkManager")) { + /* There is another manager. UNMANAGED. */ + return TRUE; + } + return FALSE; } - return FALSE; + return NM_OPTION_BOOL_DEFAULT; } /** @@ -2173,9 +2201,12 @@ nm_platform_link_change(NMPlatform *self, int ifindex, NMPlatformLinkProps *props, NMPlatformLinkBondPort *bond_port, + NMPlatformLinkBridgePort *bridge_port, NMPlatformLinkChangeFlags flags) { - char sbuf_prio[100]; + NMPortKind port_kind = NM_PORT_KIND_NONE; + NMPlatformLinkPortData port_data; + char sbuf_prio[100]; _CHECK_SELF(self, klass, FALSE); @@ -2187,6 +2218,7 @@ nm_platform_link_change(NMPlatform *self, | NM_PLATFORM_LINK_CHANGE_GSO_MAX_SEGMENTS | NM_PLATFORM_LINK_CHANGE_GRO_MAX_SIZE) || props); + nm_assert((!!bond_port + !!bridge_port) <= 1); if (_LOGD_ENABLED()) { nm_auto_free_gstring GString *str = g_string_new(""); @@ -2210,6 +2242,12 @@ nm_platform_link_change(NMPlatform *self, !bond_port->prio_has ? "?" : "", bond_port->prio) : ""); + } else if (bridge_port) { + g_string_append_printf(str, + "bridge-port path_cost %u priority %u hairpin %s", + bridge_port->path_cost, + bridge_port->priority, + bridge_port->hairpin ? "true" : "false"); } if (str->len > 0 && str->str[str->len - 1] == ' ') @@ -2218,12 +2256,15 @@ nm_platform_link_change(NMPlatform *self, _LOG3D("link: change: %s", str->str); } - return klass->link_change(self, - ifindex, - props, - bond_port ? NM_PORT_KIND_BOND : NM_PORT_KIND_NONE, - (const NMPlatformLinkPortData *) bond_port, - flags); + if (bond_port) { + port_data.bond = *bond_port; + port_kind = NM_PORT_KIND_BOND; + } else if (bridge_port) { + port_data.bridge = *bridge_port; + port_kind = NM_PORT_KIND_BRIDGE; + } + + return klass->link_change(self, ifindex, props, port_kind, &port_data, flags); } /** @@ -2482,6 +2523,12 @@ nm_platform_link_get_lnk_gretap(NMPlatform *self, int ifindex, const NMPlatformL return _link_get_lnk(self, ifindex, NM_LINK_TYPE_GRETAP, out_link); } +const NMPlatformLnkHsr * +nm_platform_link_get_lnk_hsr(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +{ + return _link_get_lnk(self, ifindex, NM_LINK_TYPE_HSR, out_link); +} + const NMPlatformLnkInfiniband * nm_platform_link_get_lnk_infiniband(NMPlatform *self, int ifindex, const NMPlatformLink **out_link) { @@ -3353,28 +3400,6 @@ nm_platform_wifi_set_wake_on_wlan(NMPlatform *self, int ifindex, _NMSettingWirel return klass->wifi_set_wake_on_wlan(self, ifindex, wowl); } -gboolean -nm_platform_wifi_get_csme_conn_info(NMPlatform *self, - int ifindex, - NMPlatformCsmeConnInfo *out_conn_info) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - - return klass->wifi_get_csme_conn_info(self, ifindex, out_conn_info); -} - -gboolean -nm_platform_wifi_get_device_from_csme(NMPlatform *self, int ifindex) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - - return klass->wifi_get_device_from_csme(self, ifindex); -} - guint32 nm_platform_mesh_get_channel(NMPlatform *self, int ifindex) { @@ -3582,6 +3607,31 @@ nm_platform_ethtool_set_ring(NMPlatform *self, int ifindex, const NMEthtoolRingS } gboolean +nm_platform_ethtool_get_link_channels(NMPlatform *self, + int ifindex, + NMEthtoolChannelsState *channels) +{ + _CHECK_SELF_NETNS(self, klass, netns, FALSE); + + g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail(channels, FALSE); + + return nmp_utils_ethtool_get_channels(ifindex, channels); +} + +gboolean +nm_platform_ethtool_set_channels(NMPlatform *self, + int ifindex, + const NMEthtoolChannelsState *channels) +{ + _CHECK_SELF_NETNS(self, klass, netns, FALSE); + + g_return_val_if_fail(ifindex > 0, FALSE); + + return nmp_utils_ethtool_set_channels(ifindex, channels); +} + +gboolean nm_platform_ethtool_get_link_pause(NMPlatform *self, int ifindex, NMEthtoolPauseState *pause) { _CHECK_SELF_NETNS(self, klass, netns, FALSE); @@ -3593,6 +3643,17 @@ nm_platform_ethtool_get_link_pause(NMPlatform *self, int ifindex, NMEthtoolPause } gboolean +nm_platform_ethtool_get_link_eee(NMPlatform *self, int ifindex, NMEthtoolEEEState *eee) +{ + _CHECK_SELF_NETNS(self, klass, netns, FALSE); + + g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail(eee, FALSE); + + return nmp_utils_ethtool_get_eee(ifindex, eee); +} + +gboolean nm_platform_ethtool_set_pause(NMPlatform *self, int ifindex, const NMEthtoolPauseState *pause) { _CHECK_SELF_NETNS(self, klass, netns, FALSE); @@ -3602,6 +3663,15 @@ nm_platform_ethtool_set_pause(NMPlatform *self, int ifindex, const NMEthtoolPaus return nmp_utils_ethtool_set_pause(ifindex, pause); } +gboolean +nm_platform_ethtool_set_eee(NMPlatform *self, int ifindex, const NMEthtoolEEEState *eee) +{ + _CHECK_SELF_NETNS(self, klass, netns, FALSE); + + g_return_val_if_fail(ifindex > 0, FALSE); + + return nmp_utils_ethtool_set_eee(ifindex, eee); +} /*****************************************************************************/ const NMDedupMultiHeadEntry * @@ -5218,6 +5288,33 @@ _route_pref_normalize(guint8 pref) : NM_ICMPV6_ROUTER_PREF_MEDIUM; } +static guint16 +_ip4_route_weight_normalize(guint n_nexthops, guint16 weight, gboolean normalize_ecmp_weight) +{ + if (n_nexthops > 1u) { + /* This is a multihop-route. The weight is relevant. + * + * We only normalize a zero to one (because in kernel such weights + * don't exist. */ + return NM_MAX(weight, 1u); + } + if (n_nexthops == 0) { + /* This route has no next-hop (e.g. blackhole type). The weight is + * always irrelevant. Normalize to zero. */ + return 0; + } + + /* We have a IPv4 single-hop route. In kernel, the weight does not exist. + * It's always zero. + * + * For upper layers, we find it useful to track such routes with a positive + * weight. They are candidates to be merged into a multi-hop ECMP route. + * + * Depending on what the caller requests, we normalize it (or leave it + * unchanged). */ + return normalize_ecmp_weight ? 0u : weight; +} + /** * nm_platform_ip_route_normalize: * @addr_family: AF_INET or AF_INET6 @@ -5230,6 +5327,15 @@ _route_pref_normalize(guint8 pref) * Note that this function is related to NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY * in that if two routes compare semantically equal, after normalizing they also shall * compare equal with NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL. + * + * Note that a positive "weight" of IPv4 single hop routes is not meaningful in + * kernel. While we track such routes at upper layers, they don't exist in + * kernel (well, they exist, with their weight set to zero, which makes them a + * different route according to NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID. It will + * be normalized to zero too, making basically it a different route. + * + * Also, "metric_any" is normalized to FALSE. This also makes it a different route + * according to NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID. */ void nm_platform_ip_route_normalize(int addr_family, NMPlatformIPRoute *route) @@ -5243,6 +5349,33 @@ nm_platform_ip_route_normalize(int addr_family, NMPlatformIPRoute *route) route->rt_source = nmp_utils_ip_config_source_round_trip_rtprot(route->rt_source); + /* For the most part, nm_platform_ip_route_normalize() tries to normalize some fields + * as it happens when they go through kernel. + * + * In most cases, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID comparison performs the same + * relaxed comparison. For example, normalize() will normalize "scope_inv", and also + * the NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID comparison will do that on-the-fly. Optimally, + * looking into a hash table gives you the same result, whether you normalize the + * needle first (or whether the entries in the hash table are normalized). + * + * Unfortunately, that's not always the case. Examples: + * + * - "metric": we have a "metric_any" field. This is used by higher layers + * to indicate that the metric is dynamically chosen (e.g. by the default + * metric of the default route). As such, as far as NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID + * is concerned, the "metric_any" and "metric" values are treated as distinguishing + * properties. But when we add a route in kernel, "metric_any" no longer exist. + * It becomes a fixed metric. Normalize will fix the metric. + * - "weight": for IPv4 single-hop routes, the weight does not exist in kernel. We however + * use the field to track ECMP information in higher layers. Consequently, + * NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID treats the weight as-is, while normalization + * (and adding it to kernel) will mangle it. + * + * You thus must be careful when you track NMPlatformIP4Route that make use of such + * higher-level features, which cannot be represented in kernel or the NMPlatform + * cache. + */ + switch (addr_family) { case AF_INET: r4 = (NMPlatformIP4Route *) route; @@ -5250,6 +5383,8 @@ nm_platform_ip_route_normalize(int addr_family, NMPlatformIPRoute *route) route->metric_any = FALSE; r4->network = nm_ip4_addr_clear_host_address(r4->network, r4->plen); r4->scope_inv = _ip_route_scope_inv_get_normalized(r4); + r4->n_nexthops = nm_platform_ip4_route_get_n_nexthops(r4); + r4->weight = _ip4_route_weight_normalize(r4->n_nexthops, r4->weight, TRUE); break; case AF_INET6: r6 = (NMPlatformIP6Route *) route; @@ -6307,6 +6442,27 @@ nm_platform_lnk_gre_to_string(const NMPlatformLnkGre *lnk, char *buf, gsize len) } const char * +nm_platform_lnk_hsr_to_string(const NMPlatformLnkHsr *lnk, char *buf, gsize len) +{ + if (!nm_utils_to_string_buffer_init_null(lnk, &buf, &len)) + return buf; + + g_snprintf(buf, + len, + "hsr " + "port1 %d " + "port2 %d " + "supervision_address " NM_ETHER_ADDR_FORMAT_STR " multicast_spec %u " + "prp %s", + lnk->port1, + lnk->port2, + NM_ETHER_ADDR_FORMAT_VAL(&lnk->supervision_address), + lnk->multicast_spec, + lnk->prp ? "on" : "off"); + return buf; +} + +const char * nm_platform_lnk_infiniband_to_string(const NMPlatformLnkInfiniband *lnk, char *buf, gsize len) { char str_p_key[64]; @@ -6983,7 +7139,7 @@ nm_platform_ip4_route_to_string_full(const NMPlatformIP4Route *route, route->plen, n_nexthops <= 1 && s_gateway[0] ? " via " : "", n_nexthops <= 1 ? s_gateway : "", - NM_PRINT_FMT_QUOTED2(n_nexthops <= 1 && route->weight != 0, + NM_PRINT_FMT_QUOTED2(n_nexthops <= 1 && route->weight != 0u, " weight ", nm_sprintf_buf(weight_str, "%u", route->weight), ""), @@ -7901,6 +8057,9 @@ nm_platform_link_hash_update(const NMPlatformLink *obj, NMHashState *h) case NM_PORT_KIND_BOND: nm_platform_link_bond_port_hash_update(&obj->port_data.bond, h); break; + case NM_PORT_KIND_BRIDGE: + nm_platform_link_bridge_port_hash_update(&obj->port_data.bridge, h); + break; } } @@ -7910,6 +8069,12 @@ nm_platform_link_bond_port_hash_update(const NMPlatformLinkBondPort *obj, NMHash nm_hash_update_vals(h, obj->prio, obj->queue_id, NM_HASH_COMBINE_BOOLS(guint8, obj->prio_has)); } +void +nm_platform_link_bridge_port_hash_update(const NMPlatformLinkBridgePort *obj, NMHashState *h) +{ + nm_hash_update_vals(h, obj->path_cost, obj->priority, obj->hairpin); +} + int nm_platform_link_cmp(const NMPlatformLink *a, const NMPlatformLink *b) { @@ -7948,6 +8113,9 @@ nm_platform_link_cmp(const NMPlatformLink *a, const NMPlatformLink *b) case NM_PORT_KIND_BOND: NM_CMP_RETURN(nm_platform_link_bond_port_cmp(&a->port_data.bond, &b->port_data.bond)); break; + case NM_PORT_KIND_BRIDGE: + NM_CMP_RETURN(nm_platform_link_bridge_port_cmp(&a->port_data.bridge, &b->port_data.bridge)); + break; } NM_CMP_FIELD(a, b, rx_packets); NM_CMP_FIELD(a, b, rx_bytes); @@ -8045,6 +8213,18 @@ nm_platform_link_bond_port_cmp(const NMPlatformLinkBondPort *a, const NMPlatform } int +nm_platform_link_bridge_port_cmp(const NMPlatformLinkBridgePort *a, + const NMPlatformLinkBridgePort *b) +{ + NM_CMP_SELF(a, b); + NM_CMP_FIELD(a, b, path_cost); + NM_CMP_FIELD(a, b, priority); + NM_CMP_FIELD(a, b, hairpin); + + return 0; +} + +int nm_platform_lnk_bond_cmp(const NMPlatformLnkBond *a, const NMPlatformLnkBond *b) { NM_CMP_SELF(a, b); @@ -8164,6 +8344,29 @@ nm_platform_lnk_gre_cmp(const NMPlatformLnkGre *a, const NMPlatformLnkGre *b) } void +nm_platform_lnk_hsr_hash_update(const NMPlatformLnkHsr *obj, NMHashState *h) +{ + nm_hash_update_vals(h, + obj->port1, + obj->port2, + obj->supervision_address, + obj->multicast_spec, + NM_HASH_COMBINE_BOOLS(guint8, obj->prp)); +} + +int +nm_platform_lnk_hsr_cmp(const NMPlatformLnkHsr *a, const NMPlatformLnkHsr *b) +{ + NM_CMP_SELF(a, b); + NM_CMP_FIELD(a, b, port1); + NM_CMP_FIELD(a, b, port2); + NM_CMP_FIELD_MEMCMP(a, b, supervision_address); + NM_CMP_FIELD(a, b, multicast_spec); + NM_CMP_FIELD_BOOL(a, b, prp); + return 0; +} + +void nm_platform_lnk_infiniband_hash_update(const NMPlatformLnkInfiniband *obj, NMHashState *h) { nm_hash_update_val(h, obj->p_key); @@ -8516,12 +8719,11 @@ nm_platform_ip4_rt_nexthop_hash_update(const NMPlatformIP4RtNextHop *obj, gboolean for_id, NMHashState *h) { - guint8 w; + guint16 w; nm_assert(obj); w = for_id ? NM_MAX(obj->weight, 1u) : obj->weight; - nm_hash_update_vals(h, obj->ifindex, obj->gateway, w); } @@ -8530,6 +8732,8 @@ nm_platform_ip4_route_hash_update(const NMPlatformIP4Route *obj, NMPlatformIPRouteCmpType cmp_type, NMHashState *h) { + guint n_nexthops; + switch (cmp_type) { case NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID: case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ECMP_ID: @@ -8567,15 +8771,17 @@ nm_platform_ip4_route_hash_update(const NMPlatformIP4Route *obj, obj->lock_mtu, obj->lock_mss)); if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) { + n_nexthops = nm_platform_ip4_route_get_n_nexthops(obj); nm_hash_update_vals(h, obj->ifindex, - nm_platform_ip4_route_get_n_nexthops(obj), + n_nexthops, obj->gateway, - (guint8) MAX(obj->weight, 1u)); + _ip4_route_weight_normalize(n_nexthops, obj->weight, FALSE)); } } break; case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY: + n_nexthops = nm_platform_ip4_route_get_n_nexthops(obj); nm_hash_update_vals( h, obj->type_coerced, @@ -8584,9 +8790,9 @@ nm_platform_ip4_route_hash_update(const NMPlatformIP4Route *obj, nm_ip4_addr_clear_host_address(obj->network, obj->plen), obj->plen, obj->metric, - nm_platform_ip4_route_get_n_nexthops(obj), + n_nexthops, obj->gateway, - (guint8) MAX(obj->weight, 1u), + _ip4_route_weight_normalize(n_nexthops, obj->weight, FALSE), nmp_utils_ip_config_source_round_trip_rtprot(obj->rt_source), _ip_route_scope_inv_get_normalized(obj), obj->tos, @@ -8652,14 +8858,9 @@ nm_platform_ip4_rt_nexthop_cmp(const NMPlatformIP4RtNextHop *a, const NMPlatformIP4RtNextHop *b, gboolean for_id) { - guint8 w_a; - guint8 w_b; + guint16 w_a; + guint16 w_b; - /* Note that weight zero is not valid (in kernel). We thus treat - * weight zero usually the same as 1. - * - * Not here for cmp/hash_update functions. These functions check for the exact - * bit-pattern, and not the it means at other places. */ NM_CMP_SELF(a, b); NM_CMP_FIELD(a, b, ifindex); NM_CMP_FIELD(a, b, gateway); @@ -8676,6 +8877,8 @@ nm_platform_ip4_route_cmp(const NMPlatformIP4Route *a, const NMPlatformIP4Route *b, NMPlatformIPRouteCmpType cmp_type) { + guint n_nexthops; + NM_CMP_SELF(a, b); switch (cmp_type) { case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ECMP_ID: @@ -8684,7 +8887,7 @@ nm_platform_ip4_route_cmp(const NMPlatformIP4Route *a, NM_CMP_FIELD_UNSAFE(a, b, table_any); NM_CMP_DIRECT(nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(a)), nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(b))); - NM_CMP_DIRECT_IP4_ADDR_SAME_PREFIX(a->network, b->network, MIN(a->plen, b->plen)); + NM_CMP_DIRECT_IP4_ADDR_SAME_PREFIX(a->network, b->network, NM_MIN(a->plen, b->plen)); NM_CMP_FIELD(a, b, plen); NM_CMP_FIELD_UNSAFE(a, b, metric_any); NM_CMP_FIELD(a, b, metric); @@ -8722,9 +8925,10 @@ nm_platform_ip4_route_cmp(const NMPlatformIP4Route *a, if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) { NM_CMP_FIELD(a, b, ifindex); NM_CMP_FIELD(a, b, gateway); - NM_CMP_DIRECT(NM_MAX(a->weight, 1u), NM_MAX(b->weight, 1u)); - NM_CMP_DIRECT(nm_platform_ip4_route_get_n_nexthops(a), - nm_platform_ip4_route_get_n_nexthops(b)); + n_nexthops = nm_platform_ip4_route_get_n_nexthops(a); + NM_CMP_DIRECT(n_nexthops, nm_platform_ip4_route_get_n_nexthops(b)); + NM_CMP_DIRECT(_ip4_route_weight_normalize(n_nexthops, a->weight, FALSE), + _ip4_route_weight_normalize(n_nexthops, b->weight, FALSE)); } } break; @@ -8739,22 +8943,22 @@ nm_platform_ip4_route_cmp(const NMPlatformIP4Route *a, NM_CMP_FIELD(a, b, table_coerced); NM_CMP_FIELD(a, b, ifindex); if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) - NM_CMP_DIRECT_IP4_ADDR_SAME_PREFIX(a->network, b->network, MIN(a->plen, b->plen)); + NM_CMP_DIRECT_IP4_ADDR_SAME_PREFIX(a->network, b->network, NM_MIN(a->plen, b->plen)); else NM_CMP_FIELD(a, b, network); NM_CMP_FIELD(a, b, plen); NM_CMP_FIELD_UNSAFE(a, b, metric_any); NM_CMP_FIELD(a, b, metric); + NM_CMP_FIELD(a, b, gateway); if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) { - NM_CMP_DIRECT(nm_platform_ip4_route_get_n_nexthops(a), - nm_platform_ip4_route_get_n_nexthops(b)); - } else + n_nexthops = nm_platform_ip4_route_get_n_nexthops(a); + NM_CMP_DIRECT(n_nexthops, nm_platform_ip4_route_get_n_nexthops(b)); + NM_CMP_DIRECT(_ip4_route_weight_normalize(n_nexthops, a->weight, FALSE), + _ip4_route_weight_normalize(n_nexthops, b->weight, FALSE)); + } else { NM_CMP_FIELD(a, b, n_nexthops); - NM_CMP_FIELD(a, b, gateway); - if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) - NM_CMP_DIRECT(NM_MAX(a->weight, 1u), NM_MAX(b->weight, 1u)); - else NM_CMP_FIELD(a, b, weight); + } if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) { NM_CMP_DIRECT(nmp_utils_ip_config_source_round_trip_rtprot(a->rt_source), nmp_utils_ip_config_source_round_trip_rtprot(b->rt_source)); @@ -8911,11 +9115,11 @@ nm_platform_ip6_route_cmp(const NMPlatformIP6Route *a, NM_CMP_FIELD_UNSAFE(a, b, table_any); NM_CMP_DIRECT(nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(a)), nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(b))); - NM_CMP_DIRECT_IP6_ADDR_SAME_PREFIX(&a->network, &b->network, MIN(a->plen, b->plen)); + NM_CMP_DIRECT_IP6_ADDR_SAME_PREFIX(&a->network, &b->network, NM_MIN(a->plen, b->plen)); NM_CMP_FIELD(a, b, plen); NM_CMP_FIELD_UNSAFE(a, b, metric_any); NM_CMP_FIELD(a, b, metric); - NM_CMP_DIRECT_IP6_ADDR_SAME_PREFIX(&a->src, &b->src, MIN(a->src_plen, b->src_plen)); + NM_CMP_DIRECT_IP6_ADDR_SAME_PREFIX(&a->src, &b->src, NM_MIN(a->src_plen, b->src_plen)); NM_CMP_FIELD(a, b, src_plen); if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) { NM_CMP_FIELD(a, b, ifindex); @@ -8934,7 +9138,7 @@ nm_platform_ip6_route_cmp(const NMPlatformIP6Route *a, NM_CMP_FIELD(a, b, table_coerced); NM_CMP_FIELD(a, b, ifindex); if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) - NM_CMP_DIRECT_IP6_ADDR_SAME_PREFIX(&a->network, &b->network, MIN(a->plen, b->plen)); + NM_CMP_DIRECT_IP6_ADDR_SAME_PREFIX(&a->network, &b->network, NM_MIN(a->plen, b->plen)); else NM_CMP_FIELD_IN6ADDR(a, b, network); NM_CMP_FIELD(a, b, plen); @@ -8943,7 +9147,7 @@ nm_platform_ip6_route_cmp(const NMPlatformIP6Route *a, NM_CMP_FIELD_IN6ADDR(a, b, gateway); NM_CMP_FIELD_IN6ADDR(a, b, pref_src); if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) { - NM_CMP_DIRECT_IP6_ADDR_SAME_PREFIX(&a->src, &b->src, MIN(a->src_plen, b->src_plen)); + NM_CMP_DIRECT_IP6_ADDR_SAME_PREFIX(&a->src, &b->src, NM_MIN(a->src_plen, b->src_plen)); NM_CMP_FIELD(a, b, src_plen); NM_CMP_DIRECT(nmp_utils_ip_config_source_round_trip_rtprot(a->rt_source), nmp_utils_ip_config_source_round_trip_rtprot(b->rt_source)); diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h index aeea5c42..996f84b8 100644 --- a/src/libnm-platform/nm-platform.h +++ b/src/libnm-platform/nm-platform.h @@ -175,8 +175,15 @@ typedef struct { bool prio_has : 1; } NMPlatformLinkBondPort; +typedef struct { + guint32 path_cost; + guint16 priority; + bool hairpin; +} NMPlatformLinkBridgePort; + typedef union { - NMPlatformLinkBondPort bond; + NMPlatformLinkBondPort bond; + NMPlatformLinkBridgePort bridge; } NMPlatformLinkPortData; struct _NMPlatformLink { @@ -437,18 +444,27 @@ struct _NMPlatformIP4Route { * pref_src must match, unless set to 0.0.0.0 to match any. */ in_addr_t pref_src; - /* This is the weight of for the first next-hop, in case of n_nexthops > 1. + /* This is the weight of for the first next-hop. * - * If n_nexthops is zero, this value is undefined (should be zero). - * If n_nexthops is 1, this also doesn't matter, but it's usually set to - * zero. - * If n_nexthops is greater or equal to one, this is the weight of - * the first hop. + * For multi-hop routes (n_nexthops > 1) this is the weight of the first + * hop. Note that the valid range is from 1-256. Zero is treated the same + * as 1 (for NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID comparison). * - * Note that upper layers (nm_utils_ip_route_attribute_to_platform()) use this flag to indicate - * whether this is a multihop route. Single-hop, non-ECMP routes will have a weight of zero. + * For routes without next-hop (e.g. blackhole type), the weight is + * meaningless. It should be set to zero. NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID + * will treat it as zero. * - * The valid range for weight in kernel is 1-256. */ + * For single-hop routes, in kernel they don't have a weight. That means, + * all routes in the platform cache have a weight of zero. For tracking + * purposes, we find it useful that upper layers have single-hop routes + * with a positive weight. Such routes can never exist in kernel. Trying + * to add such a route will somewhat work, because + * nm_platform_ip_route_normalize() normalizes the weight to zero + * (effectively adding another route, according to + * NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID). A lookup in the platform cache with + * such a route will not yield a result. It does not exist there. If you + * want to find such a route, normalize it first. + */ guint16 weight; /* rtm_tos (iproute2: tos) @@ -697,13 +713,11 @@ typedef struct { typedef struct { int ifindex; in_addr_t gateway; - /* The valid range for weight is 1-256. Single hop routes in kernel - * don't have a weight, we assign them weight zero (to indicate the - * weight is missing). + + /* The weight of the next hop. The valid range for weight is 1-256. * - * Upper layers (nm_utils_ip_route_attribute_to_platform()) care about - * the distinction of unset weight (no-ECMP). They express no-ECMP as - * zero. + * Zero is allowed too, but treated as 1 (by + * NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID comparison). */ guint16 weight; @@ -829,6 +843,14 @@ typedef struct { } _nm_alignas(NMPlatformObject) NMPlatformLnkGre; typedef struct { + int port1; + int port2; + NMEtherAddr supervision_address; + guint8 multicast_spec; + bool prp : 1; +} _nm_alignas(NMPlatformObject) NMPlatformLnkHsr; + +typedef struct { int p_key; const char *mode; } _nm_alignas(NMPlatformObject) NMPlatformLnkInfiniband; @@ -1009,14 +1031,6 @@ typedef struct { /*****************************************************************************/ -typedef struct _NMPlatformCsmeConnInfo { - guint8 ssid[32]; - guint32 channel; - NMEtherAddr addr; - guint8 sta_cipher; - guint8 auth_mode; -} NMPlatformCsmeConnInfo; - typedef enum { NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_L3MDEV, NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_UID_RANGE, @@ -1242,10 +1256,6 @@ typedef struct { gboolean (*wifi_set_wake_on_wlan)(NMPlatform *self, int ifindex, _NMSettingWirelessWakeOnWLan wowl); - gboolean (*wifi_get_csme_conn_info)(NMPlatform *self, - int ifindex, - NMPlatformCsmeConnInfo *out_conn_info); - gboolean (*wifi_get_device_from_csme)(NMPlatform *self, int ifindex); guint32 (*mesh_get_channel)(NMPlatform *self, int ifindex); gboolean (*mesh_set_channel)(NMPlatform *self, int ifindex, guint32 channel); @@ -1641,7 +1651,7 @@ const NMPlatformLink *nm_platform_link_get_by_address(NMPlatform *self, gconstpointer address, size_t length); -GPtrArray *nm_platform_link_get_all(NMPlatform *self, gboolean sort_by_name); +GPtrArray *nm_platform_link_get_all(NMPlatform *self); int nm_platform_link_add(NMPlatform *self, NMLinkType type, @@ -1748,6 +1758,17 @@ nm_platform_link_gre_add(NMPlatform *self, } static inline int +nm_platform_link_hsr_add(NMPlatform *self, + const char *name, + const NMPlatformLnkHsr *props, + const NMPlatformLink **out_link) +{ + g_return_val_if_fail(props, -NME_BUG); + + return nm_platform_link_add(self, NM_LINK_TYPE_HSR, name, 0, NULL, 0, 0, props, out_link); +} + +static inline int nm_platform_link_sit_add(NMPlatform *self, const char *name, const NMPlatformLnkSit *props, @@ -1946,9 +1967,9 @@ int nm_platform_link_get_master(NMPlatform *self, int slave); gboolean nm_platform_link_can_assume(NMPlatform *self, int ifindex); -gboolean nm_platform_link_get_unmanaged(NMPlatform *self, int ifindex, gboolean *unmanaged); -gboolean nm_platform_link_supports_slaves(NMPlatform *self, int ifindex); -const char *nm_platform_link_get_type_name(NMPlatform *self, int ifindex); +NMOptionBool nm_platform_link_get_unmanaged(NMPlatform *self, int ifindex); +gboolean nm_platform_link_supports_slaves(NMPlatform *self, int ifindex); +const char *nm_platform_link_get_type_name(NMPlatform *self, int ifindex); gboolean nm_platform_link_refresh(NMPlatform *self, int ifindex); void nm_platform_process_events(NMPlatform *self); @@ -1983,6 +2004,7 @@ gboolean nm_platform_link_change(NMPlatform *self, int ifindex, NMPlatformLinkProps *props, NMPlatformLinkBondPort *bond_port, + NMPlatformLinkBridgePort *bridge_port, NMPlatformLinkChangeFlags flags); gboolean nm_platform_link_get_udev_property(NMPlatform *self, @@ -2065,6 +2087,8 @@ const NMPlatformLnkGre * nm_platform_link_get_lnk_gre(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkGre * nm_platform_link_get_lnk_gretap(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); +const NMPlatformLnkHsr * +nm_platform_link_get_lnk_hsr(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkIp6Tnl * nm_platform_link_get_lnk_ip6tnl(NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkIp6Tnl * @@ -2146,10 +2170,6 @@ void nm_platform_wifi_indicate_addressing_running(NMPlatform *self, int ifindex, _NMSettingWirelessWakeOnWLan nm_platform_wifi_get_wake_on_wlan(NMPlatform *self, int ifindex); gboolean nm_platform_wifi_set_wake_on_wlan(NMPlatform *self, int ifindex, _NMSettingWirelessWakeOnWLan wowl); -gboolean nm_platform_wifi_get_csme_conn_info(NMPlatform *self, - int ifindex, - NMPlatformCsmeConnInfo *out_conn_info); -gboolean nm_platform_wifi_get_device_from_csme(NMPlatform *self, int ifindex); guint32 nm_platform_mesh_get_channel(NMPlatform *self, int ifindex); gboolean nm_platform_mesh_set_channel(NMPlatform *self, int ifindex, guint32 channel); @@ -2391,6 +2411,7 @@ const char *nm_platform_link_to_string(const NMPlatformLink *link, char *buf, gs const char *nm_platform_lnk_bond_to_string(const NMPlatformLnkBond *lnk, char *buf, gsize len); const char *nm_platform_lnk_bridge_to_string(const NMPlatformLnkBridge *lnk, char *buf, gsize len); const char *nm_platform_lnk_gre_to_string(const NMPlatformLnkGre *lnk, char *buf, gsize len); +const char *nm_platform_lnk_hsr_to_string(const NMPlatformLnkHsr *lnk, char *buf, gsize len); const char * nm_platform_lnk_infiniband_to_string(const NMPlatformLnkInfiniband *lnk, char *buf, gsize len); const char *nm_platform_lnk_ip6tnl_to_string(const NMPlatformLnkIp6Tnl *lnk, char *buf, gsize len); @@ -2444,6 +2465,7 @@ int nm_platform_link_cmp(const NMPlatformLink *a, const NMPlatformLink *b); int nm_platform_lnk_bond_cmp(const NMPlatformLnkBond *a, const NMPlatformLnkBond *b); int nm_platform_lnk_bridge_cmp(const NMPlatformLnkBridge *a, const NMPlatformLnkBridge *b); int nm_platform_lnk_gre_cmp(const NMPlatformLnkGre *a, const NMPlatformLnkGre *b); +int nm_platform_lnk_hsr_cmp(const NMPlatformLnkHsr *a, const NMPlatformLnkHsr *b); int nm_platform_lnk_infiniband_cmp(const NMPlatformLnkInfiniband *a, const NMPlatformLnkInfiniband *b); int nm_platform_lnk_ip6tnl_cmp(const NMPlatformLnkIp6Tnl *a, const NMPlatformLnkIp6Tnl *b); @@ -2484,8 +2506,11 @@ int nm_platform_mptcp_addr_cmp(const NMPlatformMptcpAddr *a, const NMPlatformMpt void nm_platform_link_hash_update(const NMPlatformLink *obj, NMHashState *h); void nm_platform_link_bond_port_hash_update(const NMPlatformLinkBondPort *obj, NMHashState *h); +void nm_platform_link_bridge_port_hash_update(const NMPlatformLinkBridgePort *obj, NMHashState *h); int nm_platform_link_bond_port_cmp(const NMPlatformLinkBondPort *a, const NMPlatformLinkBondPort *b); +int nm_platform_link_bridge_port_cmp(const NMPlatformLinkBridgePort *a, + const NMPlatformLinkBridgePort *b); void nm_platform_ip4_route_hash_update(const NMPlatformIP4Route *obj, NMPlatformIPRouteCmpType cmp_type, NMHashState *h); @@ -2512,6 +2537,7 @@ void nm_platform_routing_rule_hash_update(const NMPlatformRoutingRule *obj, void nm_platform_lnk_bond_hash_update(const NMPlatformLnkBond *obj, NMHashState *h); void nm_platform_lnk_bridge_hash_update(const NMPlatformLnkBridge *obj, NMHashState *h); void nm_platform_lnk_gre_hash_update(const NMPlatformLnkGre *obj, NMHashState *h); +void nm_platform_lnk_hsr_hash_update(const NMPlatformLnkHsr *obj, NMHashState *h); void nm_platform_lnk_infiniband_hash_update(const NMPlatformLnkInfiniband *obj, NMHashState *h); void nm_platform_lnk_ip6tnl_hash_update(const NMPlatformLnkIp6Tnl *obj, NMHashState *h); void nm_platform_lnk_ipip_hash_update(const NMPlatformLnkIpIp *obj, NMHashState *h); @@ -2572,12 +2598,24 @@ gboolean nm_platform_ethtool_get_link_ring(NMPlatform *self, int ifindex, NMEtht gboolean nm_platform_ethtool_set_ring(NMPlatform *self, int ifindex, const NMEthtoolRingState *ring); +gboolean nm_platform_ethtool_get_link_channels(NMPlatform *self, + int ifindex, + NMEthtoolChannelsState *channels); + +gboolean nm_platform_ethtool_set_channels(NMPlatform *self, + int ifindex, + const NMEthtoolChannelsState *channels); + gboolean nm_platform_ethtool_get_link_pause(NMPlatform *self, int ifindex, NMEthtoolPauseState *pause); +gboolean nm_platform_ethtool_get_link_eee(NMPlatform *self, int ifindex, NMEthtoolEEEState *eee); + gboolean nm_platform_ethtool_set_pause(NMPlatform *self, int ifindex, const NMEthtoolPauseState *pause); +gboolean nm_platform_ethtool_set_eee(NMPlatform *self, int ifindex, const NMEthtoolEEEState *eee); + void nm_platform_ip4_dev_route_blacklist_set(NMPlatform *self, int ifindex, GPtrArray *ip4_dev_route_blacklist); diff --git a/src/libnm-platform/nmp-base.h b/src/libnm-platform/nmp-base.h index ffe59363..70b5d1bc 100644 --- a/src/libnm-platform/nmp-base.h +++ b/src/libnm-platform/nmp-base.h @@ -93,16 +93,12 @@ typedef struct { const NMEthtoolFeatureState states_list[]; } NMEthtoolFeatureStates; -/*****************************************************************************/ - typedef struct { guint32 s[_NM_ETHTOOL_ID_COALESCE_NUM /* indexed by (NMEthtoolID - _NM_ETHTOOL_ID_COALESCE_FIRST) */ ]; } NMEthtoolCoalesceState; -/*****************************************************************************/ - typedef struct { guint32 rx_pending; guint32 rx_mini_pending; @@ -116,6 +112,17 @@ typedef struct { bool tx : 1; } NMEthtoolPauseState; +typedef struct { + guint32 rx; + guint32 tx; + guint32 other; + guint32 combined; +} NMEthtoolChannelsState; + +typedef struct { + bool enabled : 1; +} NMEthtoolEEEState; + /*****************************************************************************/ typedef struct _NMPNetns NMPNetns; @@ -152,6 +159,7 @@ typedef enum _nm_packed { NMP_OBJECT_TYPE_LNK_BRIDGE, NMP_OBJECT_TYPE_LNK_GRE, NMP_OBJECT_TYPE_LNK_GRETAP, + NMP_OBJECT_TYPE_LNK_HSR, NMP_OBJECT_TYPE_LNK_INFINIBAND, NMP_OBJECT_TYPE_LNK_IP6TNL, NMP_OBJECT_TYPE_LNK_IP6GRE, diff --git a/src/libnm-platform/nmp-object.c b/src/libnm-platform/nmp-object.c index 7e3fb1a3..4090da71 100644 --- a/src/libnm-platform/nmp-object.c +++ b/src/libnm-platform/nmp-object.c @@ -3485,6 +3485,18 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_gre_hash_update, .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_gre_cmp, }, + [NMP_OBJECT_TYPE_LNK_HSR - 1] = + { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_LNK_HSR, + .sizeof_data = sizeof(NMPObjectLnkHsr), + .sizeof_public = sizeof(NMPlatformLnkHsr), + .obj_type_name = "hsr", + .lnk_link_type = NM_LINK_TYPE_HSR, + .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_hsr_to_string, + .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_hsr_hash_update, + .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_hsr_cmp, + }, [NMP_OBJECT_TYPE_LNK_INFINIBAND - 1] = { .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), diff --git a/src/libnm-platform/nmp-object.h b/src/libnm-platform/nmp-object.h index 408f0318..19cace3d 100644 --- a/src/libnm-platform/nmp-object.h +++ b/src/libnm-platform/nmp-object.h @@ -254,6 +254,10 @@ typedef struct { } NMPObjectLnkGre; typedef struct { + NMPlatformLnkHsr _public; +} NMPObjectLnkHsr; + +typedef struct { NMPlatformLnkInfiniband _public; } NMPObjectLnkInfiniband; @@ -377,6 +381,9 @@ struct _NMPObject { NMPlatformLnkGre lnk_gre; NMPObjectLnkGre _lnk_gre; + NMPlatformLnkHsr lnk_hsr; + NMPObjectLnkHsr _lnk_hsr; + NMPlatformLnkInfiniband lnk_infiniband; NMPObjectLnkInfiniband _lnk_infiniband; @@ -530,6 +537,7 @@ _NMP_OBJECT_TYPE_IS_OBJ_WITH_IFINDEX(NMPObjectType obj_type) case NMP_OBJECT_TYPE_LNK_BOND: case NMP_OBJECT_TYPE_LNK_GRE: case NMP_OBJECT_TYPE_LNK_GRETAP: + case NMP_OBJECT_TYPE_LNK_HSR: case NMP_OBJECT_TYPE_LNK_INFINIBAND: case NMP_OBJECT_TYPE_LNK_IP6TNL: case NMP_OBJECT_TYPE_LNK_IP6GRE: diff --git a/src/libnm-platform/nmp-plobj.c b/src/libnm-platform/nmp-plobj.c index d3643ae1..70664634 100644 --- a/src/libnm-platform/nmp-plobj.c +++ b/src/libnm-platform/nmp-plobj.c @@ -424,7 +424,7 @@ nm_platform_ip4_address_to_string(const NMPlatformIP4Address *address, char *buf (address->lifetime == address->preferred) ? str_lft_p : (_lifetime_to_string(address->timestamp, - address->lifetime ? MIN(address->preferred, address->lifetime) + address->lifetime ? NM_MIN(address->preferred, address->lifetime) : NM_PLATFORM_LIFETIME_PERMANENT, now, str_pref, @@ -522,7 +522,7 @@ nm_platform_ip6_address_to_string(const NMPlatformIP6Address *address, char *buf (address->lifetime == address->preferred) ? str_lft_p : (_lifetime_to_string(address->timestamp, - address->lifetime ? MIN(address->preferred, address->lifetime) + address->lifetime ? NM_MIN(address->preferred, address->lifetime) : NM_PLATFORM_LIFETIME_PERMANENT, now, str_pref, diff --git a/src/libnm-platform/nmp-plobj.h b/src/libnm-platform/nmp-plobj.h index 35c81509..ad18573f 100644 --- a/src/libnm-platform/nmp-plobj.h +++ b/src/libnm-platform/nmp-plobj.h @@ -17,7 +17,7 @@ * also "packed" is specified. That's what we want. * https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#Common-Type-Attributes. */ -#define _NMPlatformObject_Align (MAX(_nm_alignof(void *), _nm_alignof(gint64))) +#define _NMPlatformObject_Align (NM_MAX_CONST(_nm_alignof(void *), _nm_alignof(gint64))) struct _NMPlatformObject { /* the object type has no fields of its own, it is only used to having diff --git a/src/libnm-platform/wifi/nm-wifi-utils-nl80211.c b/src/libnm-platform/wifi/nm-wifi-utils-nl80211.c index beddaf22..6109849a 100644 --- a/src/libnm-platform/wifi/nm-wifi-utils-nl80211.c +++ b/src/libnm-platform/wifi/nm-wifi-utils-nl80211.c @@ -696,10 +696,12 @@ nl80211_wiphy_info_handler(const struct nl_msg *msg, void *arg) info->caps |= _NM_WIFI_DEVICE_CAP_FREQ_VALID; - if (f->freq > 2400 && f->freq < 2500) + if (f->freq >= 2401 && f->freq <= 2495) info->caps |= _NM_WIFI_DEVICE_CAP_FREQ_2GHZ; - if (f->freq > 4900 && f->freq < 6000) + if (f->freq >= 5150 && f->freq <= 5895) info->caps |= _NM_WIFI_DEVICE_CAP_FREQ_5GHZ; + if (f->freq >= 5925 && f->freq <= 7125) + info->caps |= _NM_WIFI_DEVICE_CAP_FREQ_6GHZ; info->num_freqs++; } @@ -825,111 +827,6 @@ nla_put_failure: g_return_val_if_reached(FALSE); } -struct nl80211_csme_conn_info { - NMWifiUtilsNl80211 *self; - NMPlatformCsmeConnInfo *conn_info; -}; - -static int -nl80211_csme_conn_event_handler(const struct nl_msg *msg, void *arg) -{ - struct nl80211_csme_conn_info *info = arg; - NMPlatformCsmeConnInfo *out_conn_info = info->conn_info; - NMWifiUtilsNl80211 *self = info->self; - struct genlmsghdr *gnlh = (void *) nlmsg_data(nlmsg_hdr(msg)); - struct nlattr *tb[NL80211_ATTR_MAX + 1]; - struct nlattr *data; - struct nlattr *attrs[NUM_IWL_MVM_VENDOR_ATTR]; - int err; - - static const struct nla_policy iwl_vendor_policy[NUM_IWL_MVM_VENDOR_ATTR] = { - [IWL_MVM_VENDOR_ATTR_AUTH_MODE] = {.type = NLA_U32}, - [IWL_MVM_VENDOR_ATTR_SSID] = {.type = NLA_UNSPEC, .maxlen = NM_IW_ESSID_MAX_SIZE}, - [IWL_MVM_VENDOR_ATTR_STA_CIPHER] = {.type = NLA_U32}, - [IWL_MVM_VENDOR_ATTR_CHANNEL_NUM] = {.type = NLA_U8}, - [IWL_MVM_VENDOR_ATTR_ADDR] = {.type = NLA_UNSPEC, .minlen = ETH_ALEN, .maxlen = ETH_ALEN}, - }; - - nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); - data = tb[NL80211_ATTR_VENDOR_DATA]; - - *out_conn_info = (NMPlatformCsmeConnInfo){}; - - err = nla_parse_nested(attrs, MAX_IWL_MVM_VENDOR_ATTR, data, iwl_vendor_policy); - if (err) { - _LOGD("IWL_MVM_VENDOR_CMD_GET_CSME_CONN_INFO Failed to parse CSME connection info: %s", - nm_strerror(err)); - return -EINVAL; - } - - if (attrs[IWL_MVM_VENDOR_ATTR_AUTH_MODE]) - out_conn_info->auth_mode = nla_get_u8(attrs[IWL_MVM_VENDOR_ATTR_AUTH_MODE]); - - if (attrs[IWL_MVM_VENDOR_ATTR_SSID]) - memcpy(out_conn_info->ssid, - nla_data(attrs[IWL_MVM_VENDOR_ATTR_SSID]), - nla_len(attrs[IWL_MVM_VENDOR_ATTR_SSID])); - - if (attrs[IWL_MVM_VENDOR_ATTR_STA_CIPHER]) - out_conn_info->sta_cipher = nla_get_u8(attrs[IWL_MVM_VENDOR_ATTR_STA_CIPHER]); - - if (attrs[IWL_MVM_VENDOR_ATTR_CHANNEL_NUM]) - out_conn_info->channel = nla_get_u8(attrs[IWL_MVM_VENDOR_ATTR_CHANNEL_NUM]); - - if (attrs[IWL_MVM_VENDOR_ATTR_ADDR]) - memcpy(&out_conn_info->addr, - nla_data(attrs[IWL_MVM_VENDOR_ATTR_ADDR]), - sizeof(out_conn_info->addr)); - - return NL_SKIP; -} - -static gboolean -wifi_nl80211_intel_vnd_get_csme_conn_info(NMWifiUtils *data, NMPlatformCsmeConnInfo *out_conn_info) -{ - NMWifiUtilsNl80211 *self = (NMWifiUtilsNl80211 *) data; - nm_auto_nlmsg struct nl_msg *msg = NULL; - int err; - struct nl80211_csme_conn_info conn_info = { - .self = self, - .conn_info = out_conn_info, - }; - - msg = nl80211_alloc_msg(self, NL80211_CMD_VENDOR, 0); - NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_ID, INTEL_OUI); - NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_SUBCMD, IWL_MVM_VENDOR_CMD_GET_CSME_CONN_INFO); - - err = nl80211_send_and_recv(self, msg, nl80211_csme_conn_event_handler, &conn_info); - if (err < 0) - _LOGD("IWL_MVM_VENDOR_CMD_GET_CSME_CONN_INFO request failed: %s", nm_strerror(err)); - - return err >= 0; - -nla_put_failure: - g_return_val_if_reached(FALSE); -} - -static gboolean -wifi_nl80211_intel_vnd_get_device_from_csme(NMWifiUtils *data) -{ - NMWifiUtilsNl80211 *self = (NMWifiUtilsNl80211 *) data; - nm_auto_nlmsg struct nl_msg *msg = NULL; - int err; - - msg = nl80211_alloc_msg(self, NL80211_CMD_VENDOR, 0); - NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_ID, INTEL_OUI); - NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_SUBCMD, IWL_MVM_VENDOR_CMD_HOST_GET_OWNERSHIP); - - err = nl80211_send_and_recv(self, msg, NULL, NULL); - if (err < 0) - _LOGD("IWL_MVM_VENDOR_CMD_HOST_GET_OWNERSHIP request failed: %s", nm_strerror(err)); - - return err >= 0; - -nla_put_failure: - g_return_val_if_reached(FALSE); -} - static void nm_wifi_utils_nl80211_init(NMWifiUtilsNl80211 *self) {} @@ -954,8 +851,6 @@ nm_wifi_utils_nl80211_class_init(NMWifiUtilsNl80211Class *klass) wifi_utils_class->get_mesh_channel = wifi_nl80211_get_mesh_channel; wifi_utils_class->set_mesh_channel = wifi_nl80211_set_mesh_channel; wifi_utils_class->set_mesh_ssid = wifi_nl80211_set_mesh_ssid; - wifi_utils_class->get_csme_conn_info = wifi_nl80211_intel_vnd_get_csme_conn_info; - wifi_utils_class->get_device_from_csme = wifi_nl80211_intel_vnd_get_device_from_csme; } NMWifiUtils * diff --git a/src/libnm-platform/wifi/nm-wifi-utils-private.h b/src/libnm-platform/wifi/nm-wifi-utils-private.h index 8fa593c0..abec38e2 100644 --- a/src/libnm-platform/wifi/nm-wifi-utils-private.h +++ b/src/libnm-platform/wifi/nm-wifi-utils-private.h @@ -7,7 +7,6 @@ #define __WIFI_UTILS_PRIVATE_H__ #include "nm-wifi-utils.h" -#include "libnm-platform/nm-platform.h" typedef struct { GObjectClass parent; @@ -55,10 +54,6 @@ typedef struct { gboolean (*set_mesh_ssid)(NMWifiUtils *data, const guint8 *ssid, gsize len); gboolean (*indicate_addressing_running)(NMWifiUtils *data, gboolean running); - - gboolean (*get_csme_conn_info)(NMWifiUtils *data, NMPlatformCsmeConnInfo *out_conn_info); - - gboolean (*get_device_from_csme)(NMWifiUtils *data); } NMWifiUtilsClass; struct NMWifiUtils { diff --git a/src/libnm-platform/wifi/nm-wifi-utils-wext.c b/src/libnm-platform/wifi/nm-wifi-utils-wext.c index 0cc8b6a6..16503430 100644 --- a/src/libnm-platform/wifi/nm-wifi-utils-wext.c +++ b/src/libnm-platform/wifi/nm-wifi-utils-wext.c @@ -548,7 +548,7 @@ wifi_wext_set_mesh_ssid(NMWifiUtils *data, const guint8 *ssid, gsize len) return FALSE; memset(buf, 0, sizeof(buf)); - memcpy(buf, ssid, MIN(sizeof(buf) - 1, len)); + memcpy(buf, ssid, NM_MIN(sizeof(buf) - 1, len)); wrq.u.essid.pointer = (caddr_t) buf; wrq.u.essid.length = len; @@ -724,8 +724,8 @@ nm_wifi_utils_wext_new(int ifindex, gboolean check_scan) guint32 response_len = 0; struct iw_range_with_scan_capa *scan_capa_range; int i; - gboolean freq_valid = FALSE, has_5ghz = FALSE, has_2ghz = FALSE; - char ifname[IFNAMSIZ]; + gboolean freq_valid = FALSE, has_6ghz = FALSE, has_5ghz = FALSE, has_2ghz = FALSE; + char ifname[IFNAMSIZ]; if (!nmp_utils_if_indextoname(ifindex, ifname)) { _LOGW(LOGD_PLATFORM | LOGD_WIFI, "can't determine interface name for ifindex %d", ifindex); @@ -758,14 +758,16 @@ nm_wifi_utils_wext_new(int ifindex, gboolean check_scan) wext->max_qual.noise = range.max_qual.noise; wext->max_qual.updated = range.max_qual.updated; - wext->num_freqs = MIN(range.num_frequency, IW_MAX_FREQUENCIES); + wext->num_freqs = NM_MIN(range.num_frequency, (guint) IW_MAX_FREQUENCIES); for (i = 0; i < wext->num_freqs; i++) { wext->freqs[i] = iw_freq_to_uint32(&range.freq[i]); freq_valid = TRUE; - if (wext->freqs[i] > 2400 && wext->freqs[i] < 2500) + if (wext->freqs[i] >= 2401 && wext->freqs[i] <= 2495) has_2ghz = TRUE; - else if (wext->freqs[i] > 4900 && wext->freqs[i] < 6000) + else if (wext->freqs[i] >= 5150 && wext->freqs[i] <= 5895) has_5ghz = TRUE; + else if (wext->freqs[i] >= 5925 && wext->freqs[i] <= 7125) + has_6ghz = TRUE; } /* Check for scanning capability; cards that can't scan are not supported */ @@ -798,6 +800,8 @@ nm_wifi_utils_wext_new(int ifindex, gboolean check_scan) wext->parent.caps |= _NM_WIFI_DEVICE_CAP_FREQ_2GHZ; if (has_5ghz) wext->parent.caps |= _NM_WIFI_DEVICE_CAP_FREQ_5GHZ; + if (has_6ghz) + wext->parent.caps |= _NM_WIFI_DEVICE_CAP_FREQ_6GHZ; _LOGI(LOGD_PLATFORM | LOGD_WIFI, "(%s): using WEXT for Wi-Fi device control", ifname); diff --git a/src/libnm-platform/wifi/nm-wifi-utils.c b/src/libnm-platform/wifi/nm-wifi-utils.c index 6f87e8c0..596ff644 100644 --- a/src/libnm-platform/wifi/nm-wifi-utils.c +++ b/src/libnm-platform/wifi/nm-wifi-utils.c @@ -157,28 +157,6 @@ nm_wifi_utils_is_wifi(int dirfd, const char *ifname) return FALSE; } -gboolean -nm_wifi_utils_get_csme_conn_info(NMWifiUtils *data, NMPlatformCsmeConnInfo *out_conn_info) -{ - NMWifiUtilsClass *klass; - - g_return_val_if_fail(data != NULL, FALSE); - - klass = NM_WIFI_UTILS_GET_CLASS(data); - return klass->get_csme_conn_info ? klass->get_csme_conn_info(data, out_conn_info) : FALSE; -} - -gboolean -nm_wifi_utils_get_device_from_csme(NMWifiUtils *data) -{ - NMWifiUtilsClass *klass; - - g_return_val_if_fail(data != NULL, FALSE); - - klass = NM_WIFI_UTILS_GET_CLASS(data); - return klass->get_device_from_csme ? klass->get_device_from_csme(data) : FALSE; -} - /* OLPC Mesh-only functions */ guint32 diff --git a/src/libnm-platform/wifi/nm-wifi-utils.h b/src/libnm-platform/wifi/nm-wifi-utils.h index 84d724a5..0532817e 100644 --- a/src/libnm-platform/wifi/nm-wifi-utils.h +++ b/src/libnm-platform/wifi/nm-wifi-utils.h @@ -62,12 +62,6 @@ _NMSettingWirelessWakeOnWLan nm_wifi_utils_get_wake_on_wlan(NMWifiUtils *data); gboolean nm_wifi_utils_set_wake_on_wlan(NMWifiUtils *data, _NMSettingWirelessWakeOnWLan wowl); -struct _NMPlatformCsmeConnInfo; -gboolean nm_wifi_utils_get_csme_conn_info(NMWifiUtils *data, - struct _NMPlatformCsmeConnInfo *out_conn_info); - -gboolean nm_wifi_utils_get_device_from_csme(NMWifiUtils *data); - /* OLPC Mesh-only functions */ guint32 nm_wifi_utils_get_mesh_channel(NMWifiUtils *data); |